zoukankan      html  css  js  c++  java
  • SpringSecurityOAuth使用JWT Token

    ⒈JWT?

      JWT(Json Web Token),是Json的一个开放的Token标准。

        1,自包含,SpringSecurityOAuth的默认Token是UUID的一个随机的无意义的字符串,并不包含任何信息,信息是被单独存放的,我们还需要通过这个令牌从单独存放信息的存储那里获取信息,所以说SpringSecurityOAuth的默认Token比较依赖于存储,一旦存储信息的存储那里出现了故障,那么这个令牌就毫无用处了。而JWT Token中是包含有意义的信息的,当我们的系统拿到这个令牌以后,我们可以直接解析这个令牌来获取有用的信息。

        2,密签,我们可以对发出去的令牌进行签名(指令牌被人篡改我们可以获知)

        3,可扩展,Token中的信息我们可以根据业务需求进行扩展。

    ⒉如何在SpringSecurityOAuth中使用JWT Token替换掉默认的UUID Token

      1.

     1         <dependency>
     2             <groupId>org.springframework.boot</groupId>
     3             <artifactId>spring-boot-starter-security</artifactId>
     4         </dependency>
     5         <dependency>
     6             <groupId>org.springframework.boot</groupId>
     7             <artifactId>spring-boot-starter-data-redis</artifactId>
     8         </dependency>
     9         <dependency>
    10             <groupId>org.springframework.boot</groupId>
    11             <artifactId>spring-boot-starter-web</artifactId>
    12         </dependency>
    13         <dependency>
    14             <groupId>org.springframework.security.oauth</groupId>
    15             <artifactId>spring-security-oauth2</artifactId>
    16             <version>2.3.5.RELEASE</version>
    17         </dependency>
    18         <dependency>
    19             <groupId>commons-collections</groupId>
    20             <artifactId>commons-collections</artifactId>
    21             <version>3.2.2</version>
    22         </dependency>
    23         <dependency>
    24             <groupId>org.springframework.boot</groupId>
    25             <artifactId>spring-boot-starter-test</artifactId>
    26             <scope>test</scope>
    27         </dependency>
    28         <dependency>
    29             <groupId>org.springframework.security</groupId>
    30             <artifactId>spring-security-test</artifactId>
    31             <scope>test</scope>
    32         </dependency>

      2.

     1 package cn.coreqi.config;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.context.annotation.Bean;
     5 import org.springframework.context.annotation.Conditional;
     6 import org.springframework.context.annotation.Configuration;
     7 import org.springframework.data.redis.connection.RedisConnectionFactory;
     8 import org.springframework.security.oauth2.provider.token.TokenStore;
     9 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    10 import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
    11 import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
    12 
    13 @Configuration
    14 public class TokenStoreConfig {
    15 
    16     @Autowired
    17     private RedisConnectionFactory redisConnectionFactory;
    18 
    19     /**
    20      * TokenStore 负责令牌的存取
    21      * @return
    22      */
    23 //    @Bean
    24 //    public TokenStore redisTokenStore(){
    25 //        return new RedisTokenStore(redisConnectionFactory);
    26 //    }
    27 
    28     @Configuration
    29     public static class JwtTokenConfig {
    30         /**
    31          * Token生成中的处理
    32          * @return
    33          */
    34         @Bean
    35         public JwtAccessTokenConverter jwtAccessTokenConverter(){
    36             JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
    37             accessTokenConverter.setSigningKey("fanqi");   //Token签名用的密钥
    38             //发出去的令牌需要密钥签名,验令牌的时候也需要令牌来验签,如果他人获知了我们的密钥
    39             //就可以用我们的密钥来签发我们的JWT令牌,JWT唯一的安全性就是密钥
    40             //别人用我们的密钥来签发我们的JWT令牌就可以随意进入我们的系统
    41             return accessTokenConverter;
    42         }
    43 
    44         @Bean
    45         public TokenStore jwtTokenStore(){
    46             return new JwtTokenStore(jwtAccessTokenConverter());
    47         }
    48     }
    49 }

      3.

     1 package cn.coreqi.config;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.beans.factory.annotation.Qualifier;
     5 import org.springframework.context.annotation.Bean;
     6 import org.springframework.context.annotation.Configuration;
     7 import org.springframework.data.redis.connection.RedisConnectionFactory;
     8 import org.springframework.security.authentication.AuthenticationManager;
     9 import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
    10 import org.springframework.security.core.userdetails.UserDetailsService;
    11 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    12 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    13 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    14 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
    15 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
    16 import org.springframework.security.oauth2.provider.token.TokenStore;
    17 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    18 import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
    19 
    20 @Configuration
    21 @EnableAuthorizationServer  //开启认证服务器
    22 public class CoreqiAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    23 
    24     @Autowired
    25     //@Qualifier("authenticationManagerBean")
    26     private AuthenticationManager authenticationManager;
    27 
    28     @Autowired
    29     private UserDetailsService userDetailsService;
    30 
    31 
    32     @Autowired
    33     private TokenStore jwtTokenStore;
    34 
    35     @Autowired(required = false)
    36     private JwtAccessTokenConverter jwtAccessTokenConverter;
    37 
    38 //    @Autowired
    39 //    private AuthenticationConfiguration authenticationConfiguration;
    40 
    41     /**
    42      * 针对端点的配置
    43      * @param authorizationServerEndpointsConfigurer
    44      * @throws Exception
    45      */
    46     @Override
    47     public void configure(AuthorizationServerEndpointsConfigurer authorizationServerEndpointsConfigurer) throws Exception {
    48         //authorizationServerEndpointsConfigurer.authenticationManager(authenticationConfiguration.getAuthenticationManager());
    49         authorizationServerEndpointsConfigurer.tokenStore(jwtTokenStore)  //使用JwtToken
    50                                             .authenticationManager(authenticationManager)
    51                                             .userDetailsService(userDetailsService);
    52         if(jwtAccessTokenConverter != null){
    53             authorizationServerEndpointsConfigurer.accessTokenConverter(jwtAccessTokenConverter);
    54         }
    55     }
    56 
    57     /**
    58      * 第三方应用客户端的有关配置
    59      * @param clientDetailsServiceConfigurer
    60      * @throws Exception
    61      */
    62     @Override
    63     public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception {
    64         clientDetailsServiceConfigurer.inMemory()
    65                 .withClient("coreqi")   //client_id
    66                 .secret("coreqiSecret") //client_id的密码
    67                 .accessTokenValiditySeconds(7200) //令牌的有效时间(单位秒)
    68                 .redirectUris("https://www.baidu.com")
    69                 .scopes("all","read","write")  //所支持的权限有那些
    70                 .authorities("COREQI_READ")
    71                 .authorizedGrantTypes("authorization_code","password"); //针对当前client所支持的授权模式
    72     }
    73 
    74     /**
    75      * 针对安全性有关的配置
    76      * @param security
    77      * @throws Exception
    78      */
    79     @Override
    80     public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    81         super.configure(security);
    82     }
    83 }

    ⒊如何扩展Jwt Token中的信息

     1 package cn.coreqi.jwt;
     2 
     3 import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
     4 import org.springframework.security.oauth2.common.OAuth2AccessToken;
     5 import org.springframework.security.oauth2.provider.OAuth2Authentication;
     6 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
     7 
     8 import java.util.HashMap;
     9 import java.util.Map;
    10 
    11 public class CoreqiJwtTokenEnhancer implements TokenEnhancer {
    12 
    13     @Override
    14     public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
    15         Map<String,Object> info = new HashMap<>();  //要往accessToken中存放的信息
    16         info.put("company","fanqi");
    17         ((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(info); //设置附加信息
    18         return accessToken;
    19     }
    20 }
     1 package cn.coreqi.config;
     2 
     3 import cn.coreqi.jwt.CoreqiJwtTokenEnhancer;
     4 import org.springframework.beans.factory.annotation.Autowired;
     5 import org.springframework.context.annotation.Bean;
     6 import org.springframework.context.annotation.Conditional;
     7 import org.springframework.context.annotation.Configuration;
     8 import org.springframework.data.redis.connection.RedisConnectionFactory;
     9 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
    10 import org.springframework.security.oauth2.provider.token.TokenStore;
    11 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    12 import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
    13 import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
    14 
    15 @Configuration
    16 public class TokenStoreConfig {
    17 
    18     @Autowired
    19     private RedisConnectionFactory redisConnectionFactory;
    20 
    21     /**
    22      * TokenStore 负责令牌的存取
    23      * @return
    24      */
    25 //    @Bean
    26 //    public TokenStore redisTokenStore(){
    27 //        return new RedisTokenStore(redisConnectionFactory);
    28 //    }
    29 
    30     @Configuration
    31     public static class JwtTokenConfig {
    32         /**
    33          * Token生成中的处理
    34          * @return
    35          */
    36         @Bean
    37         public JwtAccessTokenConverter jwtAccessTokenConverter(){
    38             JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
    39             accessTokenConverter.setSigningKey("fanqi");   //Token签名用的密钥
    40             //发出去的令牌需要密钥签名,验令牌的时候也需要令牌来验签,如果他人获知了我们的密钥
    41             //就可以用我们的密钥来签发我们的JWT令牌,JWT唯一的安全性就是密钥
    42             //别人用我们的密钥来签发我们的JWT令牌就可以随意进入我们的系统
    43             return accessTokenConverter;
    44         }
    45 
    46         @Bean
    47         public TokenStore jwtTokenStore(){
    48             return new JwtTokenStore(jwtAccessTokenConverter());
    49         }
    50 
    51         @Bean
    52         public TokenEnhancer jwtTokenEnhancer(){
    53             return new CoreqiJwtTokenEnhancer();
    54         }
    55     }
    56 }
     1 package cn.coreqi.config;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.beans.factory.annotation.Qualifier;
     5 import org.springframework.context.annotation.Bean;
     6 import org.springframework.context.annotation.Configuration;
     7 import org.springframework.data.redis.connection.RedisConnectionFactory;
     8 import org.springframework.security.authentication.AuthenticationManager;
     9 import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
    10 import org.springframework.security.core.userdetails.UserDetailsService;
    11 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    12 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    13 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    14 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
    15 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
    16 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
    17 import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
    18 import org.springframework.security.oauth2.provider.token.TokenStore;
    19 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
    20 import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
    21 
    22 import java.util.ArrayList;
    23 import java.util.List;
    24 
    25 @Configuration
    26 @EnableAuthorizationServer  //开启认证服务器
    27 public class CoreqiAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    28 
    29     @Autowired
    30     //@Qualifier("authenticationManagerBean")
    31     private AuthenticationManager authenticationManager;
    32 
    33     @Autowired
    34     private UserDetailsService userDetailsService;
    35 
    36 
    37     @Autowired
    38     private TokenStore jwtTokenStore;
    39 
    40     @Autowired(required = false)
    41     private JwtAccessTokenConverter jwtAccessTokenConverter;
    42 
    43     @Autowired(required = false)
    44     private TokenEnhancer jwtTokenEnhancer;
    45 
    46 //    @Autowired
    47 //    private AuthenticationConfiguration authenticationConfiguration;
    48 
    49     /**
    50      * 针对端点的配置
    51      * @param authorizationServerEndpointsConfigurer
    52      * @throws Exception
    53      */
    54     @Override
    55     public void configure(AuthorizationServerEndpointsConfigurer authorizationServerEndpointsConfigurer) throws Exception {
    56         //authorizationServerEndpointsConfigurer.authenticationManager(authenticationConfiguration.getAuthenticationManager());
    57         authorizationServerEndpointsConfigurer.tokenStore(jwtTokenStore)  //使用JwtToken
    58                                             .authenticationManager(authenticationManager)
    59                                             .userDetailsService(userDetailsService);
    60         if(jwtAccessTokenConverter != null && jwtTokenEnhancer != null){
    61             TokenEnhancerChain enhancerChain = new TokenEnhancerChain();    //Token增强器
    62             List<TokenEnhancer> enhancers = new ArrayList<>();
    63             enhancers.add(jwtTokenEnhancer);
    64             enhancers.add(jwtAccessTokenConverter);
    65             enhancerChain.setTokenEnhancers(enhancers);
    66             authorizationServerEndpointsConfigurer.tokenEnhancer(enhancerChain)
    67                     .accessTokenConverter(jwtAccessTokenConverter);
    68         }
    69     }
    70 
    71     /**
    72      * 第三方应用客户端的有关配置
    73      * @param clientDetailsServiceConfigurer
    74      * @throws Exception
    75      */
    76     @Override
    77     public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception {
    78         clientDetailsServiceConfigurer.inMemory()
    79                 .withClient("coreqi")   //client_id
    80                 .secret("coreqiSecret") //client_id的密码
    81                 .accessTokenValiditySeconds(7200) //令牌的有效时间(单位秒)
    82                 .redirectUris("https://www.baidu.com")
    83                 .scopes("all","read","write")  //所支持的权限有那些
    84                 .authorities("COREQI_READ")
    85                 .authorizedGrantTypes("authorization_code","password"); //针对当前client所支持的授权模式
    86     }
    87 
    88     /**
    89      * 针对安全性有关的配置
    90      * @param security
    91      * @throws Exception
    92      */
    93     @Override
    94     public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    95         super.configure(security);
    96     }
    97 }

    ⒋控制器如何识别Token中扩展的信息

    1 <dependency>
    2     <groupId>io.jsonwebtoken</groupId>
    3     <artifactId>jjwt</artifactId>
    4     <version>0.9.1</version>
    5 </dependency>
     1 package cn.coreqi.controller;
     2 
     3 
     4 import io.jsonwebtoken.Claims;
     5 import io.jsonwebtoken.Jwts;
     6 import org.apache.commons.lang.StringUtils;
     7 import org.springframework.web.bind.annotation.GetMapping;
     8 import org.springframework.web.bind.annotation.RestController;
     9 
    10 import javax.servlet.http.HttpServletRequest;
    11 import java.io.UnsupportedEncodingException;
    12 import java.net.Authenticator;
    13 
    14 @RestController
    15 public class UserController {
    16 
    17     @GetMapping("/user/me")
    18     public Object getCurrentUser(Authenticator user , HttpServletRequest request) throws UnsupportedEncodingException {
    19         String header = request.getHeader("Authorization");
    20         String token = StringUtils.substringAfter(header,"bearer ");
    21         Claims claims = Jwts.parser().setSigningKey("fanqi".getBytes("UTF-8")).parseClaimsJws(token).getBody();
    22         String company = (String) claims.get("company");
    23         System.out.println(company);
    24         return user;
    25     }
    26 }
  • 相关阅读:
    Manage by Xcode
    CrashLog查看
    关于NSDateFormatter的格式dd是月天,DD是年天
    【转】 XCode的一些调试技巧
    应用程序互相跳转
    【转】如何将TapkuLibrary框架添加到Xcode4工程项目中
    NSString initWithBytes: 有最大值限制
    在一个workspace中的 各个工程 最好设置一致
    从桌面应用自动化测试看移动应用自动化测试
    基于Android平台应用程序的关键字驱动自动化测试 – 理论、工具和实践
  • 原文地址:https://www.cnblogs.com/fanqisoft/p/10669851.html
Copyright © 2011-2022 走看看