三 配置授权服务器

创建认证服务auth

(1)引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-jwt</artifactId>
    <version>1.1.1.RELEASE</version>
</dependency>

第一步、创建配置类

自定义配置类OAuth2AuthorizationServer,继承AuthorizationServerConfigurerAdapter,添加注解
@Configuration
@EnableAuthorizationServer

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServer extends AuthorizationServerConfigurerAdapter {

}

重写AuthorizationServerConfigurerAdapter中的三个方法,配置授权服务器

public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {

    public AuthorizationServerConfigurerAdapter() {
    }

    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    }

    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    }

    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    }
}

这三个方法的作用:

ClientDetailsServiceConfigurer:
配置客户端信息,客户端信息在这里进行初始化,可以在这里写死也可以通过数据库来存储和调取

AuthorizationServerEndpointsConfigurer:
配置令牌服务和令牌的访问端点

AuthorizationServerSecurityConfigurer:
配置令牌端点的安全约束

第二步、配置客户端信息

配置客户端信息的 主要配置项:
clientId:客户端id
secret: 客户端秘钥
scope:允许的授权范围
authorizedGrantTypes:允许客户端使用的授权类型
authorities:客户端可以使用的权限

客户端信息 能够在应用程序运行的时候进行更新 可以使用内存存储也可以存储在关系型数据库中

接下来演示用内存的方式存储客户端信息,配置如下:

    /**
     * 配置基于内存或JDBC的客户端信息
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()// 使用内存存储
                .withClient("c1")//客户端id
                .secret(new BCryptPasswordEncoder().encode("secret"))//客户端秘钥
                .resourceIds("res1")//资源列表
                /**
                 * 允许给客户端授权的5种授权类型:
                 *  1 "authorization_code"  授权码模式, 2 "password" 密码模式, 3 "client_credentials" 客户端模式
                 *  4 "implicit" 隐式模式, 5 "refresh_token" 刷新令牌
                 */
                .authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")

                .scopes("all")//允许的授权范围
                .autoApprove(false) //false: 如果是授权码模式 跳转到授权页面
                .redirectUris("http://www.baidu.com");//加上验证回调地址
    }

3、令牌服务底层实现原理

(1)底层源码分析:
AuthorizationServerTokenServices接口定义了一些操作使得你可以对令牌进行一些必要的管理;

DefaultTokenServices是AuthorizationServerTokenServices的实现类,可以使用它来设置令牌的格式和令牌的存储;

默认创建一个令牌时,使用随机值进行填充,除了持久化令牌是委托一个TokenStore接口来实现以外,其他功能都由DefaultTokenServices实现;

TokenStore这个接口有一个默认的实现类InMemoryTokenStore,如其命名,所有的令牌都被保存在了内存中。

(2)TokenStore的3个实现类简介:
InMemoryTokenStore:该实现类被默认采用,这种方式是将令牌保存到内存中,可以在开发阶段使用它做调试;

JdbcTokenStore:这是一个基于JDBC的实现类,令牌会被保存进关系型数据库。这种实现方式可以在不同的服务器之间共享令牌信息,使用该实现类要导入spring-jdbc依赖

JwtTokenStore:它可以把令牌相关的数据进行编码,不需要进行存储

4、令牌服务代码实现

    @Autowired
    ClientDetailsService clientDetailsService;

    @Autowired
    TokenStore tokenStore;

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    @Bean
    public AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setClientDetailsService(clientDetailsService);
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setTokenStore(tokenStore);
        tokenServices.setAccessTokenValiditySeconds(7200); //令牌默认有效期2小时
        tokenServices.setRefreshTokenValiditySeconds(259200); //刷新令牌默认有效期3天

        return tokenServices;
    }

5、令牌访问端点配置

(1)配置授权类型

authenticationManager:
用于密码授权模式

authorizationCodeServices:
用于授权码模式

implicitGrantService:
用于设置隐式授权模式

userDetailsService:
配置自定义的userDetailsService实现类

tokenGranter:
四种授权模式不满足需求的情况下,做扩展增强
https://www.toobug.cn/post/2865.html

(2)配置授权端点的URL:

我们可以通过AuthorizationServerEndpointsConfigurer 对象的 pathMapping() 方法来配置端点URL链接,它有两个参数:
第一个参数:String 类型,它是这个端点URL的默认链接
第二个参数:String 类型,它是你要替换的URL链接

框架的默认URL链接如下:
/oauth/authorize:授权端点
/oauth/token:令牌端点
/oauth/confirm_access:用户确认授权提交端点
/oauth/error:授权服务错误信息端点
/oauth/check_token:用于资源服务访问的令牌解析端点
/oauth/token_key:如果使用的是JWT令牌,则为 提供公有密匙的端点

需要注意的是授权端点这个URL应该被spring security保护起来,只供授权用户访问

6、配置令牌端点的安全约束

AuthorizationServerSecurityConfigurer用来配置令牌端点的安全约束,配置如下:

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                 //tokenkey端点完全公开
                .tokenKeyAccess("permitAll()")

                 //checkToken端点完全公开
                .checkTokenAccess("permitAll()")
                 
                //允许表单认证
                .allowFormAuthenticationForClients();
    }

web安全配置

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 为特定的Http请求配置基于Web的安全约束
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭csrf
        http.csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                //对于登录接口,允许匿名访问
                .antMatchers("/user/login").anonymous() //匿名访问(未登录可访问,登录后不可访问)
                .antMatchers("/user/hello").hasAuthority("system:test:index")
                .anyRequest().authenticated();
        //允许跨域
        http.cors();
    }

    /**
     * 实例化AuthenticationManager对象,将它注入spring容器
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容