zoukankan      html  css  js  c++  java
  • spring sercurity+redis实现每次登陆生成不同的token

    在实际开发中,使用spring sercurity+redis生成并保存token会出现,不同客户端使用的时同一个token(都是存储在redis中),这将造成,其中一个客户端注销,

    其他客户端也被注销了,极大的影响了开发效率,于是通过阅读源码,对token的生成做了修改,实现了每次登陆都是新的token。

    参考地址:https://blog.csdn.net/gangsijay888/article/details/81977796

    1、DefaultTokenServices

    DefaultTokenServices类的createAccessToken方法将会通过当前登陆的用户信息从redis中获取token,若存在,则直接返回,否则生成新的。

     1 @Transactional
     2     public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
     3                 //从redis中获取登陆信息
     4         OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
     5         OAuth2RefreshToken refreshToken = null;
     6         if (existingAccessToken != null) {
     7             if (existingAccessToken.isExpired()) {
     8                 if (existingAccessToken.getRefreshToken() != null) {
     9                     refreshToken = existingAccessToken.getRefreshToken();
    10                     // The token store could remove the refresh token when the
    11                     // access token is removed, but we want to
    12                     // be sure...
    13                     tokenStore.removeRefreshToken(refreshToken);
    14                 }
    15                 tokenStore.removeAccessToken(existingAccessToken);
    16             }
    17             else {
    18                 // Re-store the access token in case the authentication has changed
    19                 tokenStore.storeAccessToken(existingAccessToken, authentication);
    20                 return existingAccessToken;
    21             }
    22         }
    23 
    24         // Only create a new refresh token if there wasn't an existing one
    25         // associated with an expired access token.
    26         // Clients might be holding existing refresh tokens, so we re-use it in
    27         // the case that the old access token
    28         // expired.
    29         if (refreshToken == null) {
    30             refreshToken = createRefreshToken(authentication);
    31         }
    32         // But the refresh token itself might need to be re-issued if it has
    33         // expired.
    34         else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
    35             ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
    36             if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
    37                 refreshToken = createRefreshToken(authentication);
    38             }
    39         }
    40 
    41         OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
    42         tokenStore.storeAccessToken(accessToken, authentication);
    43         // In case it was modified
    44         refreshToken = accessToken.getRefreshToken();
    45         if (refreshToken != null) {
    46             tokenStore.storeRefreshToken(refreshToken, authentication);
    47         }
    48         return accessToken;
    49 
    50     }    
    View Code

    2、RedisTokenStore

     1 @Override
     2     public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
     3               //根据登陆时的用户信息并按照一定规则生成key,然后通过key从Reid是中获取 
     4              //数据
     5         String key = authenticationKeyGenerator.extractKey(authentication);
     6         byte[] serializedKey = serializeKey(AUTH_TO_ACCESS + key);
     7         byte[] bytes = null;
     8         RedisConnection conn = getConnection();
     9         try {
    10             bytes = conn.get(serializedKey);
    11         } finally {
    12             conn.close();
    13         }
    14         OAuth2AccessToken accessToken = deserializeAccessToken(bytes);
    15         if (accessToken != null) {
    16             OAuth2Authentication storedAuthentication = readAuthentication(accessToken.getValue());
    17             if ((storedAuthentication == null || !key.equals(authenticationKeyGenerator.extractKey(storedAuthentication)))) {
    18                 // Keep the stores consistent (maybe the same user is
    19                 // represented by this authentication but the details have
    20                 // changed)
    21                 storeAccessToken(accessToken, authentication);
    22             }
    23 
    24         }
    25         return accessToken;
    26     }
    View Code

    3、自定义key的生成规则

    通过自定义key的生成规则,实现每次登陆都生成新的token。

     1 public class MyAuthenticationKeyGenerator extends DefaultAuthenticationKeyGenerator {
     2 
     3     private static final String CLIENT_ID = "client_id";
     4 
     5     private static final String SCOPE = "scope";
     6 
     7     private static final String USERNAME = "username";
     8 
     9     @Override
    10     public String extractKey(OAuth2Authentication authentication) {
    11         Map<String, String> values = new LinkedHashMap<String, String>();
    12         OAuth2Request authorizationRequest = authentication.getOAuth2Request();
    13         if (!authentication.isClientOnly()) {
    14             //在用户名后面添加时间戳,使每次的key都不一样
    15             values.put(USERNAME, authentication.getName()+System.currentTimeMillis());
    16         }
    17         values.put(CLIENT_ID, authorizationRequest.getClientId());
    18         if (authorizationRequest.getScope() != null) {
    19             values.put(SCOPE, OAuth2Utils.formatParameterList(new TreeSet<String>(authorizationRequest.getScope())));
    20         }
    21         return generateKey(values);
    22     }
    23 }
    View Code

    4、将自定义的key生成规则注入到RedisTokenStore中

    @Configuration
    public class MyTokenStoreConfig {
    
       //同一个账户是否每次登陆使用同一个token
        @Value("${token.oneAccount.onlyOne}")
        private boolean onlyOne;
    
        @Autowired
        private RedisConnectionFactory redisConnectionFactory;
    
        @Bean
        public TokenStore tokenStore() {
            RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
            if (!onlyOne){
                redisTokenStore.setAuthenticationKeyGenerator(new MyAuthenticationKeyGenerator());
            }
            return redisTokenStore;
        }
    }

     

  • 相关阅读:
    cocos2d JS 在 JavaScript 中,怎样把一个对象转化成 JSON 字符串?
    cocos2d-x 暂停/恢复 与场景相关(SceneGraph类型)的监听器
    cocos2d CCNode类(节点属性大全)
    cocos2d-x 错误异常抛出捕获和崩溃拦截
    cocos2d JS 鼠标响应事件
    cocos2d JS 创建实现换行功能的聊天文本 testLable
    cocos2d JS 自定义事件分发器(接收与传递数据) eventManager
    cocos2d JS 监听键盘触摸响应事件(cc.EventListener.KEYBOARD)
    cocos2d JS touch(触摸监听)-快速添加事件监听器到管理器
    cocos2dx C++ imageView(图片/九宫格)相关属性大全
  • 原文地址:https://www.cnblogs.com/cq-yangzhou/p/13207069.html
Copyright © 2011-2022 走看看