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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM