Start from SpringSecurity under sanbanax micro service

1. Introduce component packages

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
Copy the code

2. Create the adapter

AuthorizationServerConfigurerAdapter is an authorized adapter, core in this adapter has the following several methods:

  • ClientDetailsServiceConfigurer

It is used to configure the ClientDetailsService. The configuration here indicates that not anyone can come to the authorization center for authorization. The client information is initialized here, either in memory or from the database, according to your own needs. A ClientDetails identifies the details of a client. The properties of a ClientDetails are as follows:

The attribute name instructions
clientId Is a unique identifier used to identify a customer
secret Client security code; Wechat login has a security code
scope It is used to restrict client access. If empty, all ranges are accessible
authrizedGrantTypes The authorization type that can be used (“authorization_code”, “password”, “client_credentials”, “implicit”, “refresh_token”), which is empty indicates that all are supported; Wechat only supports authorization_code;
authorities Available to clients (based on Spring Security Authorities)
redirectUris Callback address to which the authorization service pushes client information

ClientDetails can be updated at run time by accessing the underlying storage media (e.g. JdbcClientDetailsService) or their implementation ClientRegisterationService ClientDetailsService to customize interface or implementation;

  • AuthorizationServerSecurityConfigurer

Configure security constraints for token endpoints; This interface contains the necessary operations for token management;

Need to implement a AuthorizationServerTokenServices interface inheritance DefaultTokenServices this class; This class contains some useful implementations that can be used to modify the token format and the token store mode; By default, when a token is created, it is populated with random values; This class does almost everything for token management, relying only on a TokenStore object in the Spring container to customize token persistence; There is a default TokenStore implementation in Spring, ImMemoryTokenStore. This class stores tokens in memory, and several TokenStore implementation classes can be used as they choose;

ImMemoryTokenStore: Memory-based;

JdbcTokenStore: JDBC based;

JwtTokenStore: JwtTokenStore: JwtTokenStore: JwtTokenStore: JwtTokenStore: JwtTokenStore All of the token information is encoded into the token itself, so that the back end does not need to maintain token-related information, which is a big advantage, but of course the disadvantage is the difficulty of revoking the token; Transmission occupies a large space;

  • AuthorizationServerEndpointsConfigurer

The access endpoint and token service used to configure the token; Grant Types are as follows:

Authorization type instructions
authenticationManager AuthenticationManager, if you select the authorization type password (resource owner password), you need to specify the authenticationManager object for authentication
userDetailsService The user principal manages the service and has its own implementation of the UserDetailsService interface. If this property is set, refresh_token refreshthe token authorization type process has an additional check step to ensure that it is still valid
authorizationCodeServices Authorization_code authorization code mode, used to set the authorization service;
implicitGrantService Used to set the status of implicit authorization mode.
tokenGranter This is for deep expansion; Once set, authorization is all yours, ignoring the above attributes;
  1 @Configuration  2 @EnableAuthorizationServer  3 @EnableConfigurationProperties(value = JwtCaProperties.class)  4 public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {  5   6     /**  7      * 属性描述:注入数据源  8      *  9      * @date : 2020/4/12 0012 上午 11:54 10      */ 11     private final DataSource dataSource; 12  13     /** 14      * 属性描述:JWT配置信息 15      * 16      * @date : 2020/4/12 0012 下午 10:49 17      */ 18     private final JwtCaProperties jwtCaProperties; 19  20     /** 21      * 属性描述:用户信息处理 22      * 23      * @date : 2020/4/13 0013 上午 12:12 24      */ 25     private final MyUserDetailServiceImpl myUserDetailServiceImpl; 26  27     private final AuthenticationManager authenticationManager; 28  29     /** 30      * 功能描述:认证中心配置 31      * 32      * @author : XXSD 33      * @date : 2020/4/12 0012 上午 11:54 34      */ 35     public AuthServerConfig(DataSource dataSource, JwtCaProperties jwtCaProperties, MyUserDetailServiceImpl myUserDetailServiceImpl, AuthenticationManager authenticationManager) { 36         this.dataSource = dataSource; 37         this.jwtCaProperties = jwtCaProperties; 38         this.myUserDetailServiceImpl = myUserDetailServiceImpl; 39         this.authenticationManager = authenticationManager; 40     } 41  42     /** 43      * 功能描述:配置第三方客户端的授权服务器安全配置 44      * <br /> 45      * 用来配置令牌的端点安全约束 46      * 47      * @author : XXSD 48      * @date : 2020/4/14 0014 下午 8:55 49      */ 50     @Override 51     public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 52         //第三方客户端校验token需要带入 clientId 和clientSecret来校验 53         security.checkTokenAccess("isAuthenticated()") 54                 //来获取我们的tokenKey需要带入clientId,clientSecret 55                 .tokenKeyAccess("isAuthenticated()"); 56         //使用表单认证的方式进行申领令牌 57         security.allowFormAuthenticationForClients(); 58     } 59  60     /** 61      * 功能描述:配置接入的客户端 62      * <br /> 63      * 用来配置客户端详情(ClientDetailsService),客户端详情杂这里进行初始化,可以把客户端详情信息写死或这通过 64      * 数据库来存储详情信息 65      * 66      * @author : XXSD 67      * @date : 2020/4/12 0012 上午 11:49 68      */ 69     @Override 70     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 71         /*//使用内存方式 72         clients.inMemory() 73                 .withClient("这里写客户端的ID") 74                 .secret(new BCryptPasswordEncoder().encode("这里放入密码")) 75                 .resourceIds("这里是客户端的资源列表") 76                 //此客户端可以使用的授权类型 77                 .authorizedGrantTypes("authorization\_code", "password", "client\_credentials", "implicit", "refresh\_token") 78                 .scopes("允许的授权范围;没有什么特殊的意义,就是一个字符串,是自己根据我们后台的服务进行的一个划分而已") 79                 //跳转到授权页面,是否显示授权页面;True标识默认用户同意,不显示授权页面 80                 .autoApprove(false) 81                 .redirectUris("这里写入你自己的回调地址"); 82                 //如果有更多的,在这里添加and 83                 .and() 84                 */ 85         clients.withClientDetails(clientDetails()); 86     } 87  88     /** 89      * 功能描述:配置Token信息 90      * <br /> 91      * 用于配置令牌(Token)的访问端点和令牌服务(TokenService) 92      * 93      * @author : XXSD 94      * @date : 2020/4/12 0012 下午 11:23 95      */ 96     @Override 97     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 98  99         /\*100         \* AuthorizationServerEndpointsConfigurer对于不同类型的授权类别也需要配置不同的属性101         * authenticationManager:102         * 认证管理器,如果你选择的是password(资源所有者密码)这个授权类型时,需要指定authenticationManager对象来进行鉴权103         * userDetailsService:104         * 用户主体管理服务,在拥有自己UserDetailsService接口的实现,如果设置了这个属性,那么refresh\_token刷新令牌的方式授权类型流程中会多一个检查的步骤,来确保是否依然有效105         * authorizationCodeServices:106         * 用于authorization\_code授权码模式,用来设置授权服务;107         * implicitGrantService:108         * 用于设置隐式授权模式的状态;109         * tokenGranter:110         * 这个是深度拓展时使用的;一旦设置,授权将会全部交由自己来掌控,会忽略以上几个属性;111         * */112 113         final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();114         //加入了之后增强器才有效果115         tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnchaner(), jwtAccessTokenConverter()));116         /\*117         \* OAuth2.0已经默认配置了几个端点:118         * /oauth/authorize:授权端点;119         * /oauth/token:令牌端点;120         * /oauth/confirm\_access:用户确认授权提交的端点;121         * /oauth/error:授权服务错误信息端点;122         * /oauth/check\_token:用于资源服务访问的令牌进行解析的端点;123         * /oauth/token\_key:使用JWT令牌需要用到的提供共有密钥的端点;124         * */125         endpoints126                 //自定义重新定义端点路径127 //                .pathMapping("")128                 .tokenStore(tokenStore())129                 .tokenEnhancer(tokenEnhancerChain)130                 .userDetailsService(myUserDetailServiceImpl)131                 //指定令牌管理服务132 //                .tokenServices(tokenServices())133                 //限制Token的信息允许提交的模式134 //                .allowedTokenEndpointRequestMethods(HttpMethod.POST);135                 .authenticationManager(authenticationManager);136     }137 138     /\*private AuthorizationServerTokenServices tokenServices(){139         final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();140         //客户端详情服务141         defaultTokenServices.setClientDetailsService(clientDetails());142         //令牌自动刷新143         defaultTokenServices.setSupportRefreshToken(true);144         //令牌存储策略145         defaultTokenServices.setTokenStore(tokenStore());146         //令牌默认有效期,当前设置为2小时;单位秒147         defaultTokenServices.setAccessTokenValiditySeconds(7200);148         //刷新令牌默认有效期,当前设置为3天;单位秒149         defaultTokenServices.setRefreshTokenValiditySeconds(259200);150 151         return defaultTokenServices;152     }\*/153 154     /\*\*155      \* 功能描述:注入基于JWT的自定义Token增强器156      \*157      \* @author : XXSD158      * @date : 2020/4/12 0012 下午 11:21159      */160     @Bean161     public AuthTokenEnchaner tokenEnchaner() {162         return new AuthTokenEnchaner();163     }164 165     /\*\*166      \* 功能描述:Token存储控制对象167      \*168      \* @author : XXSD169      * @date : 2020/4/12 0012 下午 1:01170      */171     @Bean172     public TokenStore tokenStore() {173         /\*174          \* Token有如下几种方式存储:175          * 1、基于内存:InMemoryTokenStore;176          * 2、基于数据库:JdbcTokenStore;177          * 3、基于Redis:RedisTokenStore;178          * 4、基于JWT:JwtTokenStore179          * 这里是基于JWT的180          * */181         return new JwtTokenStore(jwtAccessTokenConverter());182     }183 184     /\*\*185      \* 功能描述:Token与用户信息之间的转换器186      \*187      \* @author : XXSD188      * @date : 2020/4/12 0012 下午 1:01189      */190     @Bean191     public JwtAccessTokenConverter jwtAccessTokenConverter() {192         final JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();193         jwtAccessTokenConverter.setKeyPair(keyPair());194         return jwtAccessTokenConverter;195     }196 197     /\*\*198      \* 功能描述:注入证书199      \*200      \* @author : XXSD201      * @date : 2020/4/12 0012 下午 11:22202      */203     @Bean204     public KeyPair keyPair() {205         KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource(jwtCaProperties.getKeyPairName()), jwtCaProperties.getKeyPairSecret().toCharArray());206         return keyStoreKeyFactory.getKeyPair(jwtCaProperties.getKeyPairAlias(), jwtCaProperties.getKeyPairStoreSecret().toCharArray());207     }208 209     /\*\*210      \* 功能描述:客户端处理服务211      \*212      \* @author : XXSD213      * @date : 2020/4/12 0012 上午 11:58214      */215     @Bean216     public ClientDetailsService clientDetails() {217         /\*218         \* 如果是使用JDBC的方式进行,那么就需要在数据库中创建一个表219         * 表的名称为:oauth\_client\_details220         * CREATE TABLE \`oauth\_client\_details\` (221             -- 标识客户端的ID;222             \`client\_id\` varchar(256) CHARACTER SET utf8 NOT NULL,223             \`resource\_ids\` varchar(256) CHARACTER SET utf8 DEFAULT NULL,224             -- 客户端安全码;225             \`client\_secret\` varchar(256) CHARACTER SET utf8 DEFAULT NULL,226             -- 用来限制客户端的访问范围,如果为空标识客户端拥有全部的访问范围227             \`scope\` varchar(256) CHARACTER SET utf8 DEFAULT NULL,228             -- authrized;此客户端可以使用的授权类型,默认为空(全部可用:authorizaton\_code、password、client\_credentals、implicit、refresh\_token);注:在微信中只支持authoriazton\_code这一种229             \`authorized\_grant\_types\` varchar(256) CHARACTER SET utf8 DEFAULT NULL,230             -- 回调的地址;授权服务会往此地址推送客户端的相关信息231             \`web\_server\_redirect\_uri\` varchar(256) CHARACTER SET utf8 DEFAULT NULL,232             -- 此客户端可以使用的权限(基于Spring Security authorities)233             \`authorities\` varchar(256) CHARACTER SET utf8 DEFAULT NULL,234             \`access\_token\_validity\` int(11) DEFAULT NULL,235             \`refresh\_token\_validity\` int(11) DEFAULT NULL,236             \`additional\_information\` varchar(4096) CHARACTER SET utf8 DEFAULT NULL,237             -- 跳转到授权页面,是否跳转到授权同意页面238             \`autoapprove\` varchar(256) CHARACTER SET utf8 DEFAULT NULL,239             PRIMARY KEY (\`client\_id\`)240             ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;241         * */242         return new JdbcClientDetailsService(dataSource);243     }244 }
Copy the code

3. Authorization center configuration

@ Configuration @ EnableWebSecuritypublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {/ * * * property description: Authentication server Loading user information object * * @date: 2020/4/13 0013 12:16 AM */ private final MyUserDetailServiceImpl MyUserDetailServiceImpl; /** * Function description: Authorization center security configuration ** @author: XXSD * @date: Public WebSecurityConfig(MyUserDetailServiceImpl MyUserDetailServiceImpl) { this.myUserDetailServiceImpl = myUserDetailServiceImpl; } /** * Function description: Used to build user authentication component, need to pass the userDetailsService and password encryption ** @author: XXSD * @date: 2020/4/13 morning 12:15 * / 0013 @ Override protected void the configure (AuthenticationManagerBuilder auth) throws the Exception { auth.userDetailsService(myUserDetailServiceImpl).passwordEncoder(passwordEncoder()); } /** * Configure a security interception policy ** @author: XXSD * @date: */ @override protected void configure(HttpSecurity HTTP) throws Exception {HTTP // Disables the CSRF cross-domain check CSRF (). The disable () / /. AuthorizeRequests () / / / / configure other request to login / /. AnyRequest () authenticated () / / / / set the parallel strategy / /. And () / / / / You can login from the default login page //.formlogin (); } /** * Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/assets/**", "/css/**", "/images/**"); ** @author: XXSD * @date: 2020/4/13 0013 aM 12:19 */ @bean public PasswordEncoder PasswordEncoder() {return BCryptPasswordEncoder(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }}Copy the code