日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

瀏覽:203日期:2023-03-11 17:00:00
背景

基于我的文章——《SpringSecurity整合springBoot、redis token動態(tài)url權(quán)限校驗》。要實現(xiàn)的功能是要實現(xiàn)一個用戶不可以同時在兩臺設(shè)備上登錄,有兩種思路:(1)后來的登錄自動踢掉前面的登錄。(2)如果用戶已經(jīng)登錄,則不允許后來者登錄。需要特別說明的是,項目的基礎(chǔ)是已經(jīng)是redis維護(hù)的session。

配置redisHttpSession

設(shè)置spring session由redis 管理。2.1去掉yml中的http session 配置,yml和注解兩者只選其一(同時配置,只有注解配置生效)。至于為什么不用yml,待會提到。

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

2.2 webSecurityConfig中加入注解@EnableRedisHttpSession

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

@EnableRedisHttpSession(redisNamespace = 'spring:session:myframe', maxInactiveIntervalInSeconds = 1700, flushMode = FlushMode.ON_SAVE)

登錄后發(fā)現(xiàn)redis session namespace已經(jīng)是我們命名的了

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

獲取redis管理的sessionRepository

我們要限制一個用戶的登錄,自然要獲取他在系統(tǒng)中的所有session。

2.再去查看springsSession官網(wǎng)的文檔。springsession官網(wǎng) 提供文檔https://docs.spring.io/spring-session/docs/ 2.2.2.RELEASE/reference/html5/#api-findbyindexnamesessionrepository

SessionRepository實現(xiàn)也可以選擇實現(xiàn)FindByIndexNameSessionRepository

FindByIndexNameSessionRepository提供一種方法,用于查找具有給定索引名稱和索引值的所有會話

FindByIndexNameSessionRepository實現(xiàn)時,可以使用方便的方法查找特定用戶的所有會話

/** * redis獲取sessionRepository * RedisIndexedSessionRepository實現(xiàn) FindByIndexNameSessionRepository接口 */ @Autowired //不加@Lazy這個會報什么循環(huán)引用... // Circular reference involving containing bean ’.RedisHttpSessionConfiguration’ @Lazy private FindByIndexNameSessionRepository<? extends Session> sessionRepository;

這里注意一點(diǎn),當(dāng)我通過yml配置redis session是,sessionRepository下面會有紅線。

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

雖然不影響運(yùn)行,但是強(qiáng)迫癥,所以改用@EnableWebSecurity注解(至于為什么?我也不想知道…)。

將sessionRepository注入SpringSessionBackedSessionRegistry

是spring session為Spring Security提供的什么會話并發(fā)的會話注冊表實現(xiàn),大概是讓springSecurity幫我們?nèi)ハ拗频卿?,光一個sessionRepository是不行的,還得自己加點(diǎn)工具什么的。webSecurityConfig加入:

/** * 是spring session為Spring Security提供的, * 用于在集群環(huán)境下控制會話并發(fā)的會話注冊表實現(xiàn) * @return */ @Bean public SpringSessionBackedSessionRegistry sessionRegistry(){return new SpringSessionBackedSessionRegistry<>(sessionRepository); }

注:https://blog.csdn.net/qq_34136709/article/details/106012825 這篇文章說還需要加一個HttpSessionEventPublisher來監(jiān)聽session銷毀云云,大概是因為我用的是redis session吧,不需要這個,要了之后還會報錯,啥錯?我忘了。

新增一個session過期后的處理類

先創(chuàng)建一個CustomSessionInformationExpiredStrategy.java來處理session過期后如何通知前端的處理類,內(nèi)容如下:

public class CustomSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy { @Override public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException {if (log.isDebugEnabled()) { log.debug('{} {}', event.getSessionInformation(), MessageConstant.SESSION_EVICT);}HttpServletResponse response = event.getResponse();response.setContentType(MediaType.APPLICATION_JSON_VALUE);response.setCharacterEncoding(StandardCharsets.UTF_8.toString());String responseJson = JackJsonUtil.object2String(ResponseFactory.fail(CodeMsgEnum.SESSION_EVICT, MessageConstant.SESSION_EVICT));response.getWriter().write(responseJson); }}

注:一般都是自己重新寫返回前端的信息,不會直接用框架拋出的錯誤信息

配置到configure(HttpSecurity http)方法上

.csrf().disable()//登錄互踢.sessionManagement()//在這里設(shè)置session的認(rèn)證策略無效//.sessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy(httpSessionConfig.sessionRegistry())).maximumSessions(1).sessionRegistry(sessionRegistry()).maxSessionsPreventsLogin(false) //false表示不阻止登錄,就是新的覆蓋舊的//session失效后要做什么(提示前端什么內(nèi)容).expiredSessionStrategy(new CustomSessionInformationExpiredStrategy());

注意:https://blog.csdn.net/qq_34136709/article/details/106012825 這篇文章說session認(rèn)證的原理,我看到它是執(zhí)行了一個session的認(rèn)證策略,但是我debug對應(yīng)的代碼時,發(fā)現(xiàn)

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

這個session認(rèn)證策略是NullAuthenticatedSessionStrategy,而不是它說的ConcurrentSessionControlAuthenticationStrategy。就是說我需要在哪里去配置這個session 認(rèn)證策略。第一時間想到了configure(HttpSecurity http)里面配置

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

結(jié)果無效。之后看到別人的代碼,想到這個策略應(yīng)該是要在登錄的時候加上去,而我們的登錄一般都需要自己重寫,自然上面的寫法會無效。于是我找到了自定義的登錄過濾器。

SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢功能

然后發(fā)現(xiàn)this.setSessionAuthenticationStrategy(sessionStrategy);確實存在。

public LoginFilter(UserVerifyAuthenticationProvider authenticationManager, CustomAuthenticationSuccessHandler successHandler, CustomAuthenticationFailureHandler failureHandler, SpringSessionBackedSessionRegistry springSessionBackedSessionRegistry) {//設(shè)置認(rèn)證管理器(對登錄請求進(jìn)行認(rèn)證和授權(quán))this.authenticationManager = authenticationManager;//設(shè)置認(rèn)證成功后的處理類this.setAuthenticationSuccessHandler(successHandler);//設(shè)置認(rèn)證失敗后的處理類this.setAuthenticationFailureHandler(failureHandler);//配置session認(rèn)證策略(將springSecurity包裝redis Session作為參數(shù)傳入)ConcurrentSessionControlAuthenticationStrategy sessionStrategy = newConcurrentSessionControlAuthenticationStrategy(springSessionBackedSessionRegistry);//最多允許一個sessionsessionStrategy.setMaximumSessions(1);this.setSessionAuthenticationStrategy(sessionStrategy);//可以自定義登錄請求的urlsuper.setFilterProcessesUrl('/myLogin'); }

啟動 后就發(fā)現(xiàn)session認(rèn)證策略已經(jīng)改為我們設(shè)定的策略了。

完整的webSecurityConfig如下:

@Configuration@EnableWebSecurity//RedisFlushMode有兩個參數(shù):ON_SAVE(表示在response commit前刷新緩存),IMMEDIATE(表示只要有更新,就刷新緩存)//yml和注解兩者只選其一(同時配置,只有注解配置生效)@EnableRedisHttpSession(redisNamespace = 'spring:session:myframe', maxInactiveIntervalInSeconds = 5000, flushMode = FlushMode.ON_SAVE)public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserVerifyAuthenticationProvider authenticationManager;//認(rèn)證用戶類 @Autowired private CustomAuthenticationSuccessHandler successHandler;//登錄認(rèn)證成功處理類 @Autowired private CustomAuthenticationFailureHandler failureHandler;//登錄認(rèn)證失敗處理類 @Autowired private MyFilterInvocationSecurityMetadataSource securityMetadataSource;//返回當(dāng)前URL允許訪問的角色列表 @Autowired private MyAccessDecisionManager accessDecisionManager;//除登錄登出外所有接口的權(quán)限校驗 /** * redis獲取sessionRepository * RedisIndexedSessionRepository實現(xiàn) FindByIndexNameSessionRepository接口 */ @Autowired //不加@Lazy這個會報什么循環(huán)引用... // Circular reference involving containing bean ’.RedisHttpSessionConfiguration’ @Lazy private FindByIndexNameSessionRepository<? extends Session> sessionRepository; /** * 是spring session為Spring Security提供的, * 用于在集群環(huán)境下控制會話并發(fā)的會話注冊表實現(xiàn) * @return */ @Bean public SpringSessionBackedSessionRegistry sessionRegistry(){return new SpringSessionBackedSessionRegistry<>(sessionRepository); } /** * 密碼加密 * @return */ @Bean @ConditionalOnMissingBean(PasswordEncoder.class) public PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(); } /** * 配置 HttpSessionIdResolver Bean * 登錄之后將會在 Response Header x-auth-token 中 返回當(dāng)前 sessionToken * 將token存儲在前端 每次調(diào)用的時候 Request Header x-auth-token 帶上 sessionToken */ @Bean public HttpSessionIdResolver httpSessionIdResolver() {return HeaderHttpSessionIdResolver.xAuthToken(); } /** * Swagger等靜態(tài)資源不進(jìn)行攔截 */ @Override public void configure(WebSecurity web) {web.ignoring().antMatchers('/*.html','/favicon.ico','/**/*.html','/**/*.css','/**/*.js','/error','/webjars/**','/resources/**','/swagger-ui.html','/swagger-resources/**','/v2/api-docs'); } @Override protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//配置一些不需要登錄就可以訪問的接口,這里配置失效了,放到了securityMetadataSource里面//.antMatchers('/demo/**', '/about/**').permitAll()//任何尚未匹配的URL只需要用戶進(jìn)行身份驗證.anyRequest().authenticated()//登錄后的接口權(quán)限校驗.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { @Override public <O extends FilterSecurityInterceptor> O postProcess(O object) {object.setAccessDecisionManager(accessDecisionManager);object.setSecurityMetadataSource(securityMetadataSource);return object; }}).and()//配置登出處理.logout().logoutUrl('/logout').logoutSuccessHandler(new CustomLogoutSuccessHandler()).clearAuthentication(true).and()//用來解決匿名用戶訪問無權(quán)限資源時的異常.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint())//用來解決登陸認(rèn)證過的用戶訪問無權(quán)限資源時的異常.accessDeniedHandler(new CustomAccessDeniedHandler()).and()//配置登錄過濾器.addFilter(new LoginFilter(authenticationManager, successHandler, failureHandler, sessionRegistry())).csrf().disable()//登錄互踢.sessionManagement()//在這里設(shè)置session的認(rèn)證策略無效//.sessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy(httpSessionConfig.sessionRegistry())).maximumSessions(1).sessionRegistry(sessionRegistry()).maxSessionsPreventsLogin(false) //false表示不阻止登錄,就是新的覆蓋舊的//session失效后要做什么(提示前端什么內(nèi)容).expiredSessionStrategy(new CustomSessionInformationExpiredStrategy());//配置頭部http.headers().contentTypeOptions().and().xssProtection().and()//禁用緩存.cacheControl().and().httpStrictTransportSecurity().and()//禁用頁面鑲嵌frame劫持安全協(xié)議 // 防止iframe 造成跨域.frameOptions().disable(); }}

其他

@Lazyprivate FindByIndexNameSessionRepository<? extends Session> sessionRepository;

至于這個不加@lazy會什么循環(huán)引用的問題,我就真的不想理會了??戳撕瞄L時間,都不知道誰和誰發(fā)生了循環(huán)引用。。。。。

到此這篇關(guān)于SpringSecurity整合springBoot、redis——實現(xiàn)登錄互踢的文章就介紹到這了,更多相關(guān)SpringSecurity登錄互踢內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲一区av| 亚洲一区成人| 日韩 欧美一区二区三区| 中文亚洲免费| 91成人网在线观看| 黄色亚洲在线| 免费精品视频| 中文在线日韩| 日韩中文字幕一区二区高清99| 亚洲欧美网站| 中文日韩欧美| 亚洲精品乱码| 日韩不卡一二三区| 欧美aⅴ一区二区三区视频| 欧美成人精品午夜一区二区| 日韩精品亚洲一区二区三区免费| 中文字幕亚洲在线观看| 日韩国产欧美在线播放| 欧美亚洲一区二区三区| 国产精品videossex久久发布| 久久久免费人体| 成人欧美一区二区三区的电影| 999精品色在线播放| 亚洲精品国产偷自在线观看| 久久午夜视频| 国产欧美一区二区三区精品观看| 久久精品国产网站| 日本国产精品| 日韩在线一区二区| 国产日产一区| 国产精品xxx在线观看| 欧美日韩在线观看首页| 国产亚洲网站| 欧美久久亚洲| 中文字幕在线视频久| 欧美日韩国产免费观看视频| 热久久久久久久| 国产精品一区二区中文字幕| 国产一二在线播放| 亚洲综合国产| 久久av国产紧身裤| 亚洲调教视频在线观看| 日韩高清电影一区| 97视频热人人精品免费| 国产亚洲精品久久久久婷婷瑜伽| 91欧美极品| 久久男人天堂| 日韩中文字幕亚洲一区二区va在线| 国产日产一区| 欧洲激情综合| 国产亚洲高清在线观看| 日本精品不卡| 日韩高清在线观看一区二区| 正在播放日韩精品| 亚洲精品少妇| 国产伦久视频在线观看| 中文字幕av一区二区三区四区| 韩日一区二区| 日韩中文字幕av电影| 水蜜桃精品av一区二区| 性色一区二区| 成人精品高清在线视频| 亚洲免费影院| 国产成人黄色| 日韩一二三区在线观看| 日韩欧美一区二区三区在线观看| 亚洲精品乱码日韩| 日韩国产一区| 欧美天堂一区二区| 免费不卡中文字幕在线| 国产精品密蕾丝视频下载| 黑丝一区二区| 精品国产乱码久久久久久樱花 | 日韩精品一二三区| 国内精品伊人| 亚洲精品观看| 久久中文字幕av一区二区不卡| 青青青国产精品| 不卡一区2区| 国产成人77亚洲精品www| 亚洲在线久久| 亚洲手机视频| 激情久久一区二区| 日韩av资源网| 在线视频日韩| 久久精品国语| 国产一区国产二区国产三区| 日韩福利视频导航| 蜜桃久久精品一区二区| 亚洲国产福利| 国产精品激情电影| 亚洲三级av| 日韩视频中文| 香蕉久久99| 亚洲国产福利| 福利欧美精品在线| 久久超级碰碰| 国产欧美日韩一区二区三区四区| 久久亚洲欧洲| 亚洲国产一区二区三区在线播放| 精品国产免费人成网站| 久久不见久久见国语| 欧美日韩网址| 日韩福利视频导航| 视频一区欧美日韩| 亚洲午夜久久久久久尤物| 精品无人区麻豆乱码久久久| 欧美综合社区国产| 日韩欧美久久| 亚洲精品成人一区| 一区二区三区网站| 日本欧美在线看| 美女黄网久久| 亚洲一卡久久| 亚洲制服少妇| 中文国产一区| 美女网站久久| 免费久久精品视频| 在线视频日韩| 亚洲精品99| 中日韩男男gay无套| 午夜电影亚洲| 香蕉国产精品| 91成人超碰| 久久最新视频| 日韩中文一区二区| 日韩va欧美va亚洲va久久| 日韩av不卡在线观看| 久久精品72免费观看| 日韩精品欧美精品| 日韩va亚洲va欧美va久久| 日本va欧美va精品发布| 日本a级不卡| 国产精品一级| 国产日韩亚洲| 欧美激情麻豆| 亚洲欧洲美洲av| 免费久久精品| 亚洲丝袜啪啪| 国产日韩欧美三区| 国产成人精品一区二区免费看京 | 亚洲高清成人| 久久精品高清| 在线一区免费观看| 亚洲一二三区视频| 国产欧美另类| 国产精品二区不卡| 久久久精品日韩| 中文久久精品| **爰片久久毛片| 国产经典一区| 日韩精品午夜| 国产精品普通话对白| 日韩一区二区三区在线看| 国产精品宾馆| 日韩一区二区三区在线免费观看| 最新亚洲一区| 蜜臀久久久久久久| 国产精品一区二区免费福利视频 | 人人香蕉久久| 日本大胆欧美人术艺术动态| 欧美中文一区| 黄色aa久久| 91久久在线| 国产香蕉精品| 日韩在线视频精品| 日韩中文字幕91| 欧美激情日韩| 91精品国产成人观看| 日韩视频一区二区三区在线播放免费观看| 亚洲一区av| 福利一区二区三区视频在线观看| 亚洲精品一二三区区别| 91精品美女| 久久精品国语| 日韩av中文在线观看| 欧美一区久久久| 一区二区国产在线| 国产videos久久| 免费看精品久久片| 欧美xxxx中国| 久久av电影| 奶水喷射视频一区| 国产一区二区三区黄网站| 性欧美xxxx免费岛国不卡电影| 日韩欧美另类中文字幕| 天堂а√在线最新版中文在线| 久久香蕉精品| 鲁鲁在线中文| 日本va欧美va精品| 免费高潮视频95在线观看网站| 蜜桃免费网站一区二区三区| 91嫩草亚洲精品| 蜜桃免费网站一区二区三区| 日韩激情一区| 欧美日韩亚洲国产精品| 欧美日韩国产综合网| 久久国产中文字幕| 国产精品1luya在线播放| 色老板在线视频一区二区|