• spring security oauth2实现多端登录互不影响


    在项目中使用spring security oauth2做了统一登录授权,在实际开发过程中,发现不同终端同一账号登录,返回的token是一样的。我们使用的是redis存储token,于是查了资料,发现是因为生成token key的算法的原因,导致了多端登录返回一个token的问题,原因如图:

    调用代码:

    生成key使用的是DefaultAuthenticationKeyGenerator,代码:

     1 public class DefaultAuthenticationKeyGenerator implements AuthenticationKeyGenerator {
     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     public String extractKey(OAuth2Authentication authentication) {
    10         Map<String, String> values = new LinkedHashMap<String, String>();
    11         OAuth2Request authorizationRequest = authentication.getOAuth2Request();
    12         if (!authentication.isClientOnly()) {
    13             values.put(USERNAME, authentication.getName());
    14         }
    15         values.put(CLIENT_ID, authorizationRequest.getClientId());
    16         if (authorizationRequest.getScope() != null) {
    17             values.put(SCOPE, OAuth2Utils.formatParameterList(new TreeSet<String>(authorizationRequest.getScope())));
    18         }
    19         return generateKey(values);
    20     }
    21 
    22     protected String generateKey(Map<String, String> values) {
    23         MessageDigest digest;
    24         try {
    25             digest = MessageDigest.getInstance("MD5");
    26             byte[] bytes = digest.digest(values.toString().getBytes("UTF-8"));
    27             return String.format("%032x", new BigInteger(1, bytes));
    28         } catch (NoSuchAlgorithmException nsae) {
    29             throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).", nsae);
    30         } catch (UnsupportedEncodingException uee) {
    31             throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).", uee);
    32         }
    33     }
    34 }

    从代码里面看,生成key使用的是 client_id、scope、username三个字段,由于这三个字段同一用户在同一子系统中是不变的,所以导致多端登录时,生成的token key是一样的,就会造成返回的token一样,这样的后果就是,其中一个终端退出登录,所有已登录设备就失效了,于是就重写这extractKey方法,继承这个类,增加了一个device_id字段,从而解决多端登录需要互不干扰的需求:

     1 public class CustomAuthenticationKeyGenerator extends DefaultAuthenticationKeyGenerator {
     2     private static final String CLIENT_ID = "client_id";
     3 
     4     private static final String SCOPE = "scope";
     5 
     6     private static final String USERNAME = "username";
     7 
     8     private static final String DEVICE_ID = "device_id";
     9 
    10     @Override
    11     public String extractKey(OAuth2Authentication authentication) {
    12         Map<String, String> values = new LinkedHashMap<String, String>();
    13         OAuth2Request authorizationRequest = authentication.getOAuth2Request();
    14         if (!authentication.isClientOnly()) {
    15             values.put(USERNAME, authentication.getName());
    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 
    22         String deviceId = authorizationRequest.getRequestParameters().get(DEVICE_ID);
    23         values.put(DEVICE_ID, deviceId);
    24 
    25         return generateKey(values);
    26     }
    27 }
  • 相关阅读:
    SQL语句大全
    SQL SERVER 用sql语句将一列数据拼接成一个字符串
    常用 SQl 语句大全
    巧用一条SQL语句实现其它进制到十进制转换
    sql 2005
    sql convert(varchar(10),getdate(),120)
    sqlserver 日期函数
    转:DBCC CHECKDB 数据库或表修复
    Linux下使用SFTP命令
    mySQL 教程 第7章 存储过程和函数
  • 原文地址:https://www.cnblogs.com/chongsha/p/14557952.html
Copyright © 2020-2023  润新知