最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2021年05月11日 15:38:33   作者:mofsfely2  
這篇文章主要介紹了SpringSecurity整合springBoot、redis實現(xiàn)登錄互踢,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

背景

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

配置redisHttpSession

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

在這里插入圖片描述

2.2 webSecurityConfig中加入注解@EnableRedisHttpSession

在這里插入圖片描述

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

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

在這里插入圖片描述

獲取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;

這里注意一點,當我通過yml配置redis session是,sessionRepository下面會有紅線。

在這里插入圖片描述

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

將sessionRepository注入SpringSessionBackedSessionRegistry

是spring session為Spring Security提供的什么會話并發(fā)的會話注冊表實現(xiàn),大概是讓springSecurity幫我們?nèi)ハ拗频卿?,光一個sessionRepository是不行的,還得自己加點工具什么的。
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的認證策略無效
//.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認證的原理,我看到它是執(zhí)行了一個session的認證策略,但是我debug對應(yīng)的代碼時,發(fā)現(xiàn)

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述
在這里插入圖片描述

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

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

啟動 后就發(fā)現(xiàn)session認證策略已經(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;//認證用戶類

    @Autowired
    private CustomAuthenticationSuccessHandler successHandler;//登錄認證成功處理類

    @Autowired
    private CustomAuthenticationFailureHandler failureHandler;//登錄認證失敗處理類

    @Autowired
    private MyFilterInvocationSecurityMetadataSource securityMetadataSource;//返回當前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 中 返回當前 sessionToken
     * 將token存儲在前端 每次調(diào)用的時候 Request Header x-auth-token 帶上 sessionToken
     */
    @Bean
    public HttpSessionIdResolver httpSessionIdResolver() {
        return HeaderHttpSessionIdResolver.xAuthToken();
    }
    /**
     * Swagger等靜態(tài)資源不進行攔截
     */
    @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只需要用戶進行身份驗證
                .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())
                //用來解決登陸認證過的用戶訪問無權(quán)限資源時的異常
                .accessDeniedHandler(new CustomAccessDeniedHandler())
                .and()
                //配置登錄過濾器
                .addFilter(new LoginFilter(authenticationManager, successHandler, failureHandler, sessionRegistry()))

                .csrf().disable()
                //登錄互踢
                .sessionManagement()
                //在這里設(shè)置session的認證策略無效
                //.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();
    }

}

其他

@Lazy
private FindByIndexNameSessionRepository<? extends Session> sessionRepository;

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

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

相關(guān)文章

  • jackson 實體轉(zhuǎn)json 為NULL或者為空不參加序列化(實例講解)

    jackson 實體轉(zhuǎn)json 為NULL或者為空不參加序列化(實例講解)

    下面小編就為大家?guī)硪黄猨ackson 實體轉(zhuǎn)json 為NULL或者為空不參加序列化(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Java設(shè)計模式--代理模式

    Java設(shè)計模式--代理模式

    代理就是一個人或者一個機構(gòu)代表另一個人或者另一個機構(gòu)采取行動。在一些情況下,一個客戶不想或者不能夠直接引用一個對象,而代理對象可以在客戶端和目標對象之前起到中介的作用
    2021-07-07
  • Java 中模仿源碼自定義ArrayList

    Java 中模仿源碼自定義ArrayList

    這篇文章主要介紹了Java 中模仿源碼自定義ArrayList的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Java?JVM虛擬機調(diào)優(yōu)詳解

    Java?JVM虛擬機調(diào)優(yōu)詳解

    JVM是JavaVirtualMachine(Java虛擬機)的縮寫,JVM是一種用于計算設(shè)備的規(guī)范,它是一個虛構(gòu)出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的,本文主要介紹了jvm調(diào)優(yōu),感興趣的小伙伴們可以參考一下<BR>
    2022-07-07
  • @MapperScan注解與@Mapper注解的使用

    @MapperScan注解與@Mapper注解的使用

    這篇文章主要介紹了@MapperScan注解與@Mapper注解的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • SpringBoot讀取resource文件代碼實例

    SpringBoot讀取resource文件代碼實例

    這篇文章主要介紹了SpringBoot讀取resource文件代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下
    2020-04-04
  • 在SpringBoot中使用Logback管理記錄日志

    在SpringBoot中使用Logback管理記錄日志

    本篇文章主要介紹了在SpringBoot中使用Logback管理記錄日志,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • java獲取系統(tǒng)路徑字體、得到某個目錄下的所有文件名、獲取當前路徑

    java獲取系統(tǒng)路徑字體、得到某個目錄下的所有文件名、獲取當前路徑

    這篇文章主要介紹了java獲取系統(tǒng)路徑字體、得到某個目錄下的所有文件名、獲取當前路徑,需要的朋友可以參考下
    2014-04-04
  • IDEA強制清除Maven緩存的方法示例

    IDEA強制清除Maven緩存的方法示例

    這篇文章主要介紹了IDEA強制清除Maven緩存的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2020-06-06
  • Spring Boot實現(xiàn)qq郵箱驗證碼注冊和登錄驗證功能

    Spring Boot實現(xiàn)qq郵箱驗證碼注冊和登錄驗證功能

    這篇文章主要給大家介紹了關(guān)于Spring Boot實現(xiàn)qq郵箱驗證碼注冊和登錄驗證功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2020-12-12

最新評論

柞水县| 自贡市| 东兴市| 盐山县| 称多县| 武功县| 米林县| 得荣县| 光山县| 海宁市| 昭苏县| 重庆市| 崇义县| 新乐市| 闽侯县| 通州区| 蚌埠市| 焦作市| 沁源县| 宜兴市| 资兴市| 洞头县| 瑞金市| 山丹县| 七台河市| 陆良县| 格尔木市| 石景山区| 高安市| 丁青县| 临夏县| 衢州市| 息烽县| 麻江县| 兴业县| 平遥县| 海淀区| 津南区| 克拉玛依市| 马关县| 白沙|