电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

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

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

配置redisHttpSession

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

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

2.2 webSecurityConfig中加入注解@EnableRedisHttpSession

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

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

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

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

獲取redis管理的sessionRepository

我們要限制一個(gè)用戶的登錄,自然要獲取他在系統(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實(shí)現(xiàn)也可以選擇實(shí)現(xiàn)FindByIndexNameSessionRepository

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

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

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

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

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

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

將sessionRepository注入SpringSessionBackedSessionRegistry

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

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

注:https://blog.csdn.net/qq_34136709/article/details/106012825 這篇文章說(shuō)還需要加一個(gè)HttpSessionEventPublisher來(lái)監(jiān)聽(tīng)session銷毀云云,大概是因?yàn)槲矣玫氖莚edis session吧,不需要這個(gè),要了之后還會(huì)報(bào)錯(cuò),啥錯(cuò)?我忘了。

新增一個(gè)session過(guò)期后的處理類

先創(chuàng)建一個(gè)CustomSessionInformationExpiredStrategy.java來(lái)處理session過(guò)期后如何通知前端的處理類,內(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); }}

注:一般都是自己重新寫(xiě)返回前端的信息,不會(huì)直接用框架拋出的錯(cuò)誤信息

配置到configure(HttpSecurity http)方法上

.csrf().disable()//登錄互踢.sessionManagement()//在這里設(shè)置session的認(rèn)證策略無(wú)效//.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 這篇文章說(shuō)session認(rèn)證的原理,我看到它是執(zhí)行了一個(gè)session的認(rèn)證策略,但是我debug對(duì)應(yīng)的代碼時(shí),發(fā)現(xiàn)

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

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

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

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

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

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

public LoginFilter(UserVerifyAuthenticationProvider authenticationManager, CustomAuthenticationSuccessHandler successHandler, CustomAuthenticationFailureHandler failureHandler, SpringSessionBackedSessionRegistry springSessionBackedSessionRegistry) {//設(shè)置認(rèn)證管理器(對(duì)登錄請(qǐng)求進(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);//最多允許一個(gè)sessionsessionStrategy.setMaximumSessions(1);this.setSessionAuthenticationStrategy(sessionStrategy);//可以自定義登錄請(qǐng)求的urlsuper.setFilterProcessesUrl('/myLogin'); }

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

完整的webSecurityConfig如下:

@Configuration@EnableWebSecurity//RedisFlushMode有兩個(gè)參數(shù):ON_SAVE(表示在response commit前刷新緩存),IMMEDIATE(表示只要有更新,就刷新緩存)//yml和注解兩者只選其一(同時(shí)配置,只有注解配置生效)@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允許訪問(wèn)的角色列表 @Autowired private MyAccessDecisionManager accessDecisionManager;//除登錄登出外所有接口的權(quán)限校驗(yàn) /** * redis獲取sessionRepository * RedisIndexedSessionRepository實(shí)現(xiàn) FindByIndexNameSessionRepository接口 */ @Autowired //不加@Lazy這個(gè)會(huì)報(bào)什么循環(huán)引用... // Circular reference involving containing bean ’.RedisHttpSessionConfiguration’ @Lazy private FindByIndexNameSessionRepository<? extends Session> sessionRepository; /** * 是spring session為Spring Security提供的, * 用于在集群環(huán)境下控制會(huì)話并發(fā)的會(huì)話注冊(cè)表實(shí)現(xiàn) * @return */ @Bean public SpringSessionBackedSessionRegistry sessionRegistry(){return new SpringSessionBackedSessionRegistry<>(sessionRepository); } /** * 密碼加密 * @return */ @Bean @ConditionalOnMissingBean(PasswordEncoder.class) public PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(); } /** * 配置 HttpSessionIdResolver Bean * 登錄之后將會(huì)在 Response Header x-auth-token 中 返回當(dāng)前 sessionToken * 將token存儲(chǔ)在前端 每次調(diào)用的時(shí)候 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()//配置一些不需要登錄就可以訪問(wèn)的接口,這里配置失效了,放到了securityMetadataSource里面//.antMatchers('/demo/**', '/about/**').permitAll()//任何尚未匹配的URL只需要用戶進(jìn)行身份驗(yàn)證.anyRequest().authenticated()//登錄后的接口權(quán)限校驗(yà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()//用來(lái)解決匿名用戶訪問(wèn)無(wú)權(quán)限資源時(shí)的異常.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint())//用來(lái)解決登陸認(rèn)證過(guò)的用戶訪問(wèn)無(wú)權(quán)限資源時(shí)的異常.accessDeniedHandler(new CustomAccessDeniedHandler()).and()//配置登錄過(guò)濾器.addFilter(new LoginFilter(authenticationManager, successHandler, failureHandler, sessionRegistry())).csrf().disable()//登錄互踢.sessionManagement()//在這里設(shè)置session的認(rèn)證策略無(wú)效//.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()//禁用頁(yè)面鑲嵌frame劫持安全協(xié)議 // 防止iframe 造成跨域.frameOptions().disable(); }}

其他

@Lazyprivate FindByIndexNameSessionRepository<? extends Session> sessionRepository;

至于這個(gè)不加@lazy會(huì)什么循環(huán)引用的問(wèn)題,我就真的不想理會(huì)了。看了好長(zhǎng)時(shí)間,都不知道誰(shuí)和誰(shuí)發(fā)生了循環(huán)引用。。。。。

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

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 苏州教学设备-化工教学设备-环境工程教学模型|同科教仪 | 安徽免检低氮锅炉_合肥燃油锅炉_安徽蒸汽发生器_合肥燃气锅炉-合肥扬诺锅炉有限公司 | 电伴热系统施工_仪表电伴热保温箱厂家_沃安电伴热管缆工业技术(济南)有限公司 | 上海皓越真空设备有限公司官网-真空炉-真空热压烧结炉-sps放电等离子烧结炉 | 无线遥控更衣吊篮_IC卡更衣吊篮_电动更衣吊篮配件_煤矿更衣吊篮-力得电子 | arch电源_SINPRO_开关电源_模块电源_医疗电源-东佑源 | 合肥卓创建筑装饰,专业办公室装饰、商业空间装修与设计。 | 金属软管_不锈钢金属软管_巩义市润达管道设备制造有限公司 | 专业生产动态配料系统_饲料配料系统_化肥配料系统等配料系统-郑州鑫晟重工机械有限公司 | hc22_hc22价格_hc22哈氏合金—东锜特殊钢| 柔性输送线|柔性链板|齿形链-上海赫勒输送设备有限公司首页[输送机] | 北京开源多邦科技发展有限公司官网| 在线PH计-氧化锆分析仪-在线浊度仪-在线溶氧仪- 无锡朝达 | 大流量卧式砂磨机_强力分散机_双行星双动力混合机_同心双轴搅拌机-莱州市龙跃化工机械有限公司 | 杭州标识标牌|文化墙|展厅|导视|户内外广告|发光字|灯箱|铭阳制作公司 - 杭州标识标牌|文化墙|展厅|导视|户内外广告|发光字|灯箱|铭阳制作公司 | 非甲烷总烃分析仪|环控百科 | 硬度计_影像测量仪_维氏硬度计_佛山市精测计量仪器设备有限公司厂家 | 锡膏喷印机-全自动涂覆机厂家-全自动点胶机-视觉点胶机-深圳市博明智控科技有限公司 | 山东活动策划|济南活动公司|济南公关活动策划-济南锐嘉广告有限公司 | 氨水-液氨-工业氨水-氨水生产厂家-辽宁顺程化工 | 烟雾净化器-滤筒除尘器-防爆除尘器-除尘器厂家-东莞执信环保科技有限公司 | 游泳池设备安装工程_恒温泳池设备_儿童游泳池设备厂家_游泳池水处理设备-东莞市君达泳池设备有限公司 | 铝机箱_铝外壳加工_铝外壳厂家_CNC散热器加工-惠州市铂源五金制品有限公司 | 盘煤仪,盘料仪,盘点仪,堆料测量仪,便携式激光盘煤仪-中科航宇(北京)自动化工程技术有限公司 | 烟气换热器_GGH烟气换热器_空气预热器_高温气气换热器-青岛康景辉 | 阿米巴企业经营-阿米巴咨询管理-阿米巴企业培训-广东键锋企业管理咨询有限公司 | 小型玉石雕刻机_家用玉雕机_小型万能雕刻机_凡刻雕刻机官网 | 网站建设-临朐爱采购-抖音运营-山东兆通网络科技 | 河南空气能热水器-洛阳空气能采暖-洛阳太阳能热水工程-洛阳润达高科空气能商行 | 集装箱展厅-住人集装箱住宿|建筑|房屋|集装箱售楼处-山东锐嘉科技工程有限公司 | 北京百度网站优化|北京网站建设公司-百谷网络科技 | 步进电机_agv电机_伺服马达-伺服轮毂电机-和利时电机 | 昆山PCB加工_SMT贴片_PCB抄板_线路板焊接加工-昆山腾宸电子科技有限公司 | 智能监控-安防监控-监控系统安装-弱电工程公司_成都万全电子 | 恒温槽_恒温水槽_恒温水浴槽-上海方瑞仪器有限公司 | 卫生人才网-中国专业的医疗卫生医学人才网招聘网站! | 旅游规划_旅游策划_乡村旅游规划_景区规划设计_旅游规划设计公司-北京绿道联合旅游规划设计有限公司 | 烟雾净化器-滤筒除尘器-防爆除尘器-除尘器厂家-东莞执信环保科技有限公司 | 泰国试管婴儿_泰国第三代试管婴儿_泰国试管婴儿费用/多少钱_孕泰来 | 镀锌钢格栅_热镀锌格栅板_钢格栅板_热镀锌钢格板-安平县昊泽丝网制品有限公司 | 分子蒸馏设备(短程分子蒸馏装置)_上海达丰仪器 |