配合OAuth2進行單設備登錄攔截

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

要進行單設備登錄,在其他地點登錄后,本地的其他操作會被攔截返回登錄界面。

原理就在于要在登錄時在redis中存儲Session,進行操作時要進行Session的比對。

具體實現,假設我們的OAuth 2的登錄調用接口如下:

共享Session,User模塊跟OAuth模塊都要設置

@Configuration
@EnableRedisHttpSession
public class SessionConfig {}

Feign

@Component
@FeignClient("oauth-center")
public interface Oauth2Client {/*** 獲取access_token<br>* 這是spring-security-oauth2底層的接口,類TokenEndpoint<br>** @param parameters* @return* @see org.springframework.security.oauth2.provider.endpoint.TokenEndpoint*/@PostMapping(path = "/api-o/oauth/token")Map<String, Object> postAccessToken(@RequestParam Map<String, String> parameters);/*** 刪除access_token和refresh_token<br>* 認證中心的OAuth2Controller方法removeToken** @param access_token*/@DeleteMapping(path = "/api-o/remove_token")void removeToken(@RequestParam("access_token") String access_token);}

Controller

/*** Created by Administrator on 2018/10/19.*/
@Slf4j
@RestController
public class UserTokenController {@Autowiredprivate Oauth2Client oauth2Client;@Resourceprivate RedisService redisServiceImpl;/*** 系統登陸<br>* 根據用戶名登錄<br>* 采用oauth2密碼模式獲取access_token和refresh_token** @param loginParam* @return*/@PostMapping("/users-anon/sys/logins")public Map<String, Object> login(@RequestBody LoginParam loginParam,HttpServletRequest request) {Map<String, String> parameters = new HashMap<>();parameters.put(OAuth2Utils.GRANT_TYPE, "password");parameters.put(OAuth2Utils.CLIENT_ID, "system");
//        parameters.put(OAuth2Utils.CLIENT_ID, "system");parameters.put("client_secret", "system");parameters.put(OAuth2Utils.SCOPE, "app");
//    parameters.put("username", username);// 為了支持多類型登錄,這里在username后拼裝上登錄類型parameters.put("username", loginParam.getUsername() + "|" + CredentialType.USERNAME.name());parameters.put("password", loginParam.getPassword());parameters.put("status","200");Map<String, Object> tokenInfo = null;try {tokenInfo = oauth2Client.postAccessToken(parameters);}catch (Exception e){e.printStackTrace();return ResponseUtils.getResult(500,"login failed");}
//        saveLoginLog(username, "用戶名密碼登陸", BlackIPAccessFilter.getIpAddress(request));return ResponseUtils.getDataResult(tokenInfo);}
}

加入Session的存儲

/*** Created by Administrator on 2018/10/19.*/
@Slf4j
@RestController
public class UserTokenController {@Autowiredprivate Oauth2Client oauth2Client;@Resourceprivate RedisService redisServiceImpl;/*** 系統登陸<br>* 根據用戶名登錄<br>* 采用oauth2密碼模式獲取access_token和refresh_token** @param loginParam* @return*/
@PostMapping("/users-anon/sys/logins")public Map<String, Object> login(@RequestBody LoginParam loginParam, HttpServletRequest request) {Map<String, String> parameters = new HashMap<>();parameters.put(OAuth2Utils.GRANT_TYPE, "password");parameters.put(OAuth2Utils.CLIENT_ID, "system");
//        parameters.put(OAuth2Utils.CLIENT_ID, "system");parameters.put("client_secret", "system");parameters.put(OAuth2Utils.SCOPE, "app");
//    parameters.put("username", username);// 為了支持多類型登錄,這里在username后拼裝上登錄類型parameters.put("username", loginParam.getUsername() + "|" + CredentialType.USERNAME.name());parameters.put("password", loginParam.getPassword());parameters.put("status","200");Map<String, Object> tokenInfo = null;try {tokenInfo = oauth2Client.postAccessToken(parameters);HttpSession session = request.getSession();String sessionId = UUID.randomUUID().toString();//此處修改為共享Sessionsession.setAttribute("sessionId", sessionId);session.setAttribute("username",loginParam.getUsername());String key = loginParam.getUsername() + "-onlyLogin";redisServiceImpl.set(key,sessionId);redisServiceImpl.expire(key,30 * 60);redisServiceImpl.hset("sessionHash",sessionId,loginParam.getUsername());}catch (Exception e){e.printStackTrace();return ResponseUtils.getResult(500,"login failed");}
//        saveLoginLog(username, "用戶名密碼登陸", BlackIPAccessFilter.getIpAddress(request));return ResponseUtils.getDataResult(tokenInfo);}
}

配置攔截器

@Slf4j
@Component
public class RedisInterceptor extends HandlerInterceptorAdapter {@Resourceprivate RedisService redisServiceImpl;@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();//讀取共享SessionString requestedSessionId = (String) session.getAttribute("sessionId");String userName = null;response.setCharacterEncoding("utf-8");response.setContentType("text/javascript;charset=utf-8");try {if (!StringUtils.isEmpty(requestedSessionId)) {userName = redisServiceImpl.hget("sessionHash", requestedSessionId);}if (StringUtils.isEmpty(userName)) {response.getWriter().write("{\"message\":\"請先登陸\"}");return false;} else {String cacheSessionId = null;String sessionKey = userName + "-onlyLogin";try {cacheSessionId = redisServiceImpl.get(sessionKey);} catch (Exception e) {e.printStackTrace();}if (StringUtils.isEmpty(cacheSessionId)) {response.getWriter().write("{\"message\":\"請先登陸\"}");return false;} else {if (!cacheSessionId.equals(requestedSessionId)) {response.getWriter().write("{\"message\":\"您的賬號已在別處登陸,請重新登陸\"}");return false;} else {redisServiceImpl.expire(sessionKey, 30 * 60);return super.preHandle(request, response, handler);}}}}catch (Exception e) {e.printStackTrace();}response.getWriter().write("{\"message\":\"服務器忙\"}");return false;}
}

攔截器就是為了獲取每次的Session,并且跟redis中的session進行比對,如果session不同,則進行攔截。

@Configuration
public class RedisSessionConfig extends WebMvcConfigurerAdapter {@Autowiredprivate RedisInterceptor redisInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(redisInterceptor).excludePathPatterns("/**/users-anon/**").excludePathPatterns("/api-o/oauth/token");super.addInterceptors(registry);}
}

這里要配置對登錄的url以及feign的url進行放行,則可以對多地點登錄時,使之前的登錄無法操作。

轉載于:https://my.oschina.net/u/3768341/blog/2885756

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450207.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450207.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450207.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

朱大鳴:中國金融危機到底有多嚴重

我們到底該不該救助金融機構&#xff0c;中國鈔票到底有沒有超發&#xff0c;對于這個問題&#xff0c;央行行長周小川日前撰文全面為之辯護&#xff1a;對于第一個問題&#xff0c;他的觀點是金融業出現了問題就必須救&#xff0c;否則意味著集體的失靈甚至死亡&#xff1b;中…

C++知識點(六)數組、指針與字符串導學

1.數組 地址連續存放初始化&#xff1a;列出全部初始值后&#xff0c;第1維下標個數可以省略不做初始化&#xff0c;局部變量中為垃圾數據&#xff0c;static變量為0只對一部分進行初始化&#xff0c;其余數值初始化為02.動態內存分配&#xff1a; new delete 3.動態創建數組 n…

Android應用開發—知識點匯總

獲取Fragment的context&#xff1a; getActivity().getApplicationContext()或者getActivity()You can use getActivity(), which returns the activity associated with a fragment.The activity is a context (since Activity extends Context).設置TextView的顏色setTextCol…

條件渲染vue

v-if:只渲染一次的情況下&#xff0c;性能更好v-show:頻繁切換性能更好 vue虛擬DOM技術 瀏覽器&#xff1a;渲染引擎&#xff08;慢&#xff09;JS引擎&#xff08;快&#xff09; 用1個JS對象來充當DOM對象&#xff0c;因為JS對象性能比較快&#xff0c;所以用虛擬DOM對象進行…

錢線觀察:貨幣基金T+0駕到 活期存款將死?

導語&#xff1a;即使沒有任何投資風險&#xff0c;通脹也在侵蝕居民的財富&#xff0c;現金是不安全的。最近出現的一項業務&#xff0c;貨幣基金"T0"贖回&#xff0c;意味著貨幣基金可以像活期存款一樣即時取現&#xff0c;而其收益率普遍高于活期存款。因此有人認…

git stash和git stash pop

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 git stash 可用來暫存當前正在進行的工作&#xff0c; 比如想pull 最新代碼&#xff0c; 又不想加新commit&#xff0c; 或者另外一種情…

CentOS 7.0 上安裝和配置 VNC 服務器

作為一個系統管理員&#xff0c;大多數時間是通過網絡管理服務器的。在管理服務器的過程中很少會用到圖形界面&#xff0c;多數情況下我們只是用 SSH 來完成我們的管理任務。在這篇文章里&#xff0c;我們將配置 VNC 來提供一個連接我們 CentOS 7 服務器的方法。VNC 允許我們開…

Android應用開發—TextView的動態創建

動態創建TextView的兩種方式&#xff1a; 下面介紹兩種創建方式&#xff1a; 在drawable里面創建共同依賴的background.xml文件&#xff0c;里面設置shape來設置文本框的一些特殊效果&#xff1a; eg&#xff1a; <?xml version"1.0" encoding"utf-8"…

Mongo DB 簡單搭建和部署

1.先下載源代碼包 官網下載地址&#xff1a;http://www.mongodb.org/downloads 2.解包tar xf mongodb-linux-x86_64-rhel62-3.2.7.tgz 3.把包移動到 /usr/local/mongodb mv mongodb-linux-x86_64-rhel62-3.2.7/ /usr/local/mongodb 指定同一時間最多可開啟的文件數&#xff08…

運算符優先級 必熟記,放到心里

優先級 運算符 名稱或含義 使用形式 結合方向 說明 1 [] 數組下標 數組名[常量表達式] 左到右 () 圓括號 &#xff08;表達式&#xff09;/函數名(形參表) . 成員選擇&#xff08;對象&#xff09; 對象.成員名 -> 成員選擇&#xff08;指針&#xff0…

可持久化平衡樹(FHQ Treap)

兩個最基本的操作 merge合并 split分割 merge 把兩棵treap合并成一棵treap&#xff0c;要滿足T1最大值要比T2最小值小&#xff0c;比較將隨機數值key值更大的作為合并后的根 假設T1作為根節點作為新子樹的根&#xff0c;左子樹不變&#xff0c;右子樹對T1原來的右子樹與T2再遞歸…

Git 分支管理-git stash 和git stash pop

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 合并分支&#xff0c;沖突是難免的&#xff0c;在實際協作開發中我們遇到的情況錯綜復雜&#xff0c;今天就講兩個比較重要的命令使用gi…

useState語法講解

useState語法講解 語法定義 const [state, dispatch] useState(initData)state&#xff1a;定義的數據源&#xff0c;可視作一個函數組件內部的變量&#xff0c;但只在首次渲染被創造。dispatch&#xff1a;改變state的函數&#xff0c;推動函數渲染的渲染函數。dispatch有兩…

NSOperation的進階使用和簡單探討

本文將會從多個方面探討NSOperation類和NSOperationQueue類的相關內容 一、簡介 NSOperation類是iOS2.0推出的&#xff0c;通過NSThread實現的,但是效率一般。 從OS X10.6和iOS4推出GCD時&#xff0c;又重寫了NSOperation和NSOperationQueue&#xff0c;NSOperation和NSOperati…

Android應用開發—LayoutParams的用法

Android應用開發—TextView的動態創建 這篇文章講到了“TextView控件布局位置的控制”&#xff0c;主要依賴于RelativeLayout.LayoutParams的使用&#xff0c;本文簡單介紹下LayoutParams的用法 注&#xff1a;本文大部分內容參考android,利用layoutParams代碼動態布局空間位置…

廖雪峰Java1-2程序基礎-7布爾運算符

布爾運算符 關系運算符&#xff1a;>&#xff0c; >&#xff0c; <&#xff0c; <&#xff0c; &#xff0c;!與運算 &&或運算 |非運算 &#xff01;int n 5;boolean t n > 0;//trueboolean f n < 0;//falseboolean isFive n 5;//trueboolean i…

第二十一屆國際C語言混亂代碼大賽結果公布

摘要&#xff1a;國際C語言混亂代碼大賽&#xff08;IOCCC, The International Obfuscated C Code Contest&#xff09;是一項著名的國際編程賽事&#xff0c;從1984年開始到2006年&#xff0c;每年舉辦一次。2006年后中止了多年&#xff0c;2011年又開始恢復。比賽的目的是寫出…

QuartZ Cron表達式

CronTrigger 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 CronTriggers往往比SimpleTrigger更有用&#xff0c;如果您需要基于日歷的概念&#xff0c;而非SimpleTrigger完全指定的時間…

maven02-----Maven項目構建的初次使用

一. 創建Maven項目 1.1 建立一個Hello項目 當然也可以通過java project的方式創建符合Maven約定的目錄結果的項目&#xff0c;并手動建立pom.xml文件&#xff0c;但是太繁瑣了。因此&#xff0c;這里直接建立maven項目。note: eclipse有內建的maven項目創建功能&#xff0c;倘若…