框架开源地址:

https://gitee.com/msxy/qingfeng-springboot-vue3-antdesign-viteicon-default.png?t=M276https://gitee.com/msxy/qingfeng-springboot-vue3-antdesign-vite

1、加入springsecurity依赖

<!--security依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--oauth2依赖-->
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.3.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-jwt</artifactId>
    <version>1.1.1.RELEASE</version>
</dependency>

2、创建认证服务类

认证服务器需要创建三大配置

认证令牌存储redis

在认证服务中,tokenStore使用的是RedisTokenStore,认证服务器生成的令牌将被存储到Redis中。此处我们需要引入redis用于存储认证服务的令牌token。

  • 认证服务配置:负责发放、校验令牌是否正确
  • 资源服务配置:这一项是可选的,因为认证服务器同样也可以是一个资源服务器。
  • WebSecurity配置:Security配置,主要处理除资源服务外的其他服务请求以及验证token的授权信息
    我们先创建认证服务类AuthorizationServerConfigure:
  • package com.qingfeng.auth.configure;
    
    import com.qingfeng.auth.service.UserDetailServiceImpl;
    import com.qingfeng.auth.translator.MyWebResponseExceptionTranslator;
    import com.qingfeng.framework.properties.AuthProperties;
    import com.qingfeng.framework.properties.ClientsProperties;
    import org.apache.commons.lang3.ArrayUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
    import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
    import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
    import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
    import org.springframework.security.oauth2.provider.token.TokenStore;
    import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
    
    /**  
    * @title: AuthorizationServerConfigure
    * @projectName: AuthorizationServerConfigure
    * @description: TODO
    * @author: Administrator
    * @date: 2021/2/21 0021 21:51
    */
    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfigure extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        private AuthenticationManager authenticationManager;
        @Autowired
        private RedisConnectionFactory redisConnectionFactory;
        @Autowired
        private UserDetailServiceImpl userDetailService;
        @Autowired
        private PasswordEncoder passwordEncoder;
        @Autowired
        private AuthProperties authProperties;
        @Autowired
        private MyWebResponseExceptionTranslator exceptionTranslator;
    
    
    //    @Override
    //    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    //        clients.inMemory()
    //                .withClient("qingfeng")
    //                .secret(passwordEncoder.encode("123456"))
    //                .authorizedGrantTypes("password", "refresh_token")
    //                .scopes("all");
    //    }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            ClientsProperties[] clientsArray = authProperties.getClients();
            InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
            if (ArrayUtils.isNotEmpty(clientsArray)) {
                for (ClientsProperties client : clientsArray) {
                    if (StringUtils.isBlank(client.getClient())) {
                        throw new Exception("client不能为空");
                    }
                    if (StringUtils.isBlank(client.getSecret())) {
                        throw new Exception("secret不能为空");
                    }
                    String[] grantTypes = StringUtils.splitByWholeSeparatorPreserveAllTokens(client.getGrantType(), ",");
                    builder.withClient(client.getClient())
                            .secret(passwordEncoder.encode(client.getSecret()))
                            .authorizedGrantTypes(grantTypes)
                            .scopes(client.getScope())
                            .accessTokenValiditySeconds(authProperties.getAccessTokenValiditySeconds())
                            .refreshTokenValiditySeconds(authProperties.getRefreshTokenValiditySeconds());
                }
            }
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
            endpoints.tokenStore(tokenStore())
                    .accessTokenConverter(jwtAccessTokenConverter())
                    .userDetailsService(userDetailService)
                    .authenticationManager(authenticationManager)
    //                .tokenServices(defaultTokenServices())
                    .exceptionTranslator(exceptionTranslator);
        }
    
        @Bean
        public TokenStore tokenStore() {
    //        return new RedisTokenStore(redisConnectionFactory);
            return new JwtTokenStore(jwtAccessTokenConverter());
        }
    
    //    @Primary
    //    @Bean
    //    public DefaultTokenServices defaultTokenServices() {
    //        DefaultTokenServices tokenServices = new DefaultTokenServices();
    //        tokenServices.setTokenStore(tokenStore());
    //        tokenServices.setSupportRefreshToken(true);
            tokenServices.setAccessTokenValiditySeconds(60 * 60 * 24);
            tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);
    //        tokenServices.setAccessTokenValiditySeconds(authProperties.getAccessTokenValiditySeconds());
    //        tokenServices.setRefreshTokenValiditySeconds(authProperties.getRefreshTokenValiditySeconds());
    //        return tokenServices;
    //    }
    
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
            DefaultAccessTokenConverter defaultAccessTokenConverter = (DefaultAccessTokenConverter) accessTokenConverter.getAccessTokenConverter();
            DefaultUserAuthenticationConverter userAuthenticationConverter = new DefaultUserAuthenticationConverter();
            userAuthenticationConverter.setUserDetailsService(userDetailService);
            defaultAccessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
            accessTokenConverter.setSigningKey("qingfeng");
            return accessTokenConverter;
        }
    
    }

    我们来介绍下认证服务类,首先@EnableAuthorizationServer表示开始认证服务。而且继承了AuthorizationServerConfigurerAdapter适配器,AuthorizationServerConfigurerAdapter包含了3个方法:

    public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
        public AuthorizationServerConfigurerAdapter() {
        }
    
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        }
    
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        }
    
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        }
    }

    分别用于配置令牌端点的安全约束、客户端信息、配置令牌端点的安全约束

    这也是我们AuthorizationServerConfigure类的骨架,其他代码都是围绕这3个方法产生的,都有注解说明。
    接下来我们分别介绍下以下几个Bean:

  • passwordEncoder:定义加密算法
  • tokenStore:定义token存储方式
  • clientDetailsService:定义客户端client信息
Logo

前往低代码交流专区

更多推荐