最近在做权限管理系统的重构工作,系统基于Spring Security + OAuth架构,整体架构、技术和之前调研的结果差不多,架构调研时有在这篇博客做过简单记录“Spring Cloud微服务下的权限架构调研”,博客未更新,和定稿的架构稍有出入,图画的也有点问题。

  前面比较忙,搭建过程没有记录,平时也没有记笔记的习惯,有点惨,写到哪算哪吧~~~

一、添加pom依赖

  项目是在Spring Cloud基础上改造的,主要记录接入Spring Security + OAuth所做的工作。这里添加security和oauth的相关依赖:

<!-- security -->
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<!-- oauth2 -->
<dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
二、配置认证服务器

  Auth作为认证服务器:

  1、新建一个认证服务器配置类,代码如下:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;
    @Autowired
    private DataSource dataSource;

    /**
     * 注册redisTokenStore,用于配置redis作为token仓库
     *
     * @return
     */
    @Bean
    public RedisTokenStore tokenStore() {
        return new RedisTokenStore(redisConnectionFactory);
    }

    /**
     * 用来配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)。
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore())
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
        endpoints.tokenServices(defaultTokenServices())
                // 重复使用refresh_token ,指导refresh_token过期,才会产生新的refresh_token
                .reuseRefreshTokens(true);

    }

    /**
     * 配置使用客户端详情服务
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService());

    }

    /**
     * 用来配置令牌端点
     *
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()");
        security.checkTokenAccess("isAuthenticated()");
        security.allowFormAuthenticationForClients();
    }

    /**
     * 注册JdbcClientDetailsService,从数据库获取客户端详情
     */
    @Bean
    public ClientDetailsService clientDetailsService() {
        return new JdbcClientDetailsService(dataSource);
    }

    /**
     * 配置token服务(仓库、客户端详情服务、是否支持refresh_token以及access_token、refresh_token的有效时间)
     */
    @Bean
    @Primary
    public DefaultTokenServices defaultTokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore());
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setClientDetailsService(clientDetailsService());
        tokenServices.setAccessTokenValiditySeconds(60 * 60 * 24); // access_token有效期,默认12小时,-1表示永不过期
        tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);//refresh_token有效期,默认30天
        return tokenServices;
    }
}

  这里有个东西要注意,在http请求进来之后,首先框架自己会先校验token的正确性。系统oauth采用的是密码模式,熟悉oauth的应该知道,在请求头中必须要带上client_id和client_secret,client_id和client_secret会base64编码后放到请求头的Authorization字段中。这些信息可以在内存、数据库里面维护,这里用的是数据库,就是在clientDetailsService()方法中配置的内容,点开JdbcClientDetailsService的源码可以看到,oauth自己维护了一个oauth_client_details表,所以我们还需要在数据库创建相应的表以及数据。除了oauth_client_details还有维护token相关的表等等,这里没用上。

public JdbcClientDetailsService(DataSource dataSource) {
        this.updateClientDetailsSql = DEFAULT_UPDATE_STATEMENT;
        this.updateClientSecretSql = "update oauth_client_details set client_secret = ? where client_id = ?";
        this.insertClientDetailsSql = "insert into oauth_client_details (client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, client_id) values (?,?,?,?,?,?,?,?,?,?,?)";
        this.selectClientDetailsSql = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?";
        this.passwordEncoder = NoOpPasswordEncoder.getInstance();
        Assert.notNull(dataSource, "DataSource required");
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.listFactory = new DefaultJdbcListFactory(new NamedParameterJdbcTemplate(this.jdbcTemplate));
    }
JdbcClientDetailsService

相关文章:

  • 2021-11-11
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-06
  • 2021-07-05
  • 2022-01-11
猜你喜欢
  • 2021-12-11
  • 2022-12-23
  • 2021-12-11
  • 2021-07-26
  • 2022-01-08
  • 2022-01-08
相关资源
相似解决方案