zoukankan      html  css  js  c++  java
  • Spring Security6、登录用户退出登录操作

    在使用过程中,如果有多个账号,需要进行账号切换。我们一般需要用户先注销当前的登录用户,然后在登录另一个账号。

    这时候我们就需要使用到退出登录的操作,在Spring Security中默认调用接口 /logout 进行登出操作,登出成功后会自动跳转到登录页面。

    在前后端分离的情况下,我们希望能像登录授权那样,登出成功后也能返回 JSON 字符串。

    一、退出登录成功处理程序

    登录失败处理程序和登录授权这些一样,我们只要实现 LogoutSuccessHandler 这个接口就可以了。

    import cn.hutool.core.lang.Console;
    import cn.hutool.core.lang.Dict;
    import cn.hutool.core.util.CharsetUtil;
    import cn.hutool.extra.servlet.ServletUtil;
    import cn.hutool.http.ContentType;
    import cn.hutool.json.JSONUtil;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * 退出成功
     *
     * @author lixin
     */
    @Component
    public class JsonLogoutSuccessHandler implements LogoutSuccessHandler {
        @Override
        public void onLogoutSuccess(
                HttpServletRequest request, HttpServletResponse response,
                Authentication authentication
        ) throws IOException, ServletException {
            Console.log("退出成功,{}", authentication);
            Dict res = Dict.create()
                    .set("code", 0)
                    .set("msg", "退出成功")
                    .set("data", authentication);
            ServletUtil.write(response, JSONUtil.toJsonStr(res), ContentType.JSON.toString(CharsetUtil.CHARSET_UTF_8));
        }
    }
    
    

    二、配置退出登录成功处理程序

    我们现在把我们写的 退出登录成功 处理程序配置到HttpSecurity上,这样在 退出登录成功 时就返回我们设置的json字符串了,完整配置看代码。

    import com.miaopasi.securitydemo.config.security.handler.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    
    /**
     * Security配置类,会覆盖yml配置文件的内容
     *
     * @author lixin
     */
    @EnableWebSecurity
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        private final JsonSuccessHandler successHandler;
        private final JsonFailureHandler failureHandler;
        private final JsonAccessDeniedHandler accessDeniedHandler;
        private final JsonAuthenticationEntryPoint authenticationEntryPoint;
        private final JsonLogoutSuccessHandler logoutSuccessHandler;
    
        @Autowired
        public SecurityConfig(JsonSuccessHandler successHandler, JsonFailureHandler failureHandler, JsonAccessDeniedHandler accessDeniedHandler, JsonAuthenticationEntryPoint authenticationEntryPoint, JsonLogoutSuccessHandler logoutSuccessHandler) {
            this.successHandler = successHandler;
            this.failureHandler = failureHandler;
            this.accessDeniedHandler = accessDeniedHandler;
            this.authenticationEntryPoint = authenticationEntryPoint;
            this.logoutSuccessHandler = logoutSuccessHandler;
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/code", "/login", "/logout", "/doLogin").permitAll()
                    .antMatchers("/admin/**", "/guest/**").hasRole("admin")
                    .antMatchers("/guest/**").hasRole("guest")
                    .anyRequest().authenticated()
                    .and().formLogin()
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .loginProcessingUrl("/doLogin")
                    .successHandler(successHandler)
                    .failureHandler(failureHandler)
                
                	// 退出登录,默认为/logout,这里修改接口地址为 /doLogout
                    .and().logout().logoutUrl("/doLogout")
                    // 设置退出登录成功处理程序,退出成功后返回JSON字符串
                    .logoutSuccessHandler(logoutSuccessHandler)
                
                    .and().exceptionHandling()
                    .accessDeniedHandler(accessDeniedHandler)
                    .authenticationEntryPoint(authenticationEntryPoint)
                    .and().cors()
                    .and().csrf().disable();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .passwordEncoder(new BCryptPasswordEncoder())
                    .withUser("admin")
                    .password(new BCryptPasswordEncoder().encode("123456"))
                    .roles("admin", "guest")
                    .and()
                    .withUser("user")
                    .password(new BCryptPasswordEncoder().encode("000000"))
                    .roles("guest");
        }
    }
    
    

    三、测试

    我们先登录用户admin,然后请求接口 /admin/get ,能正常访问。

    然后我们使用get方式调用接口 /doLogout,接口返回JSON字符串:

    {
      "msg": "退出成功",
      "code": 0,
      "data": {
        "authenticated": true,
        "authorities": [
          {},
          {}
        ],
        "principal": {
          "credentialsNonExpired": true,
          "authorities": [
            {},
            {}
          ],
          "enabled": true,
          "accountNonExpired": true,
          "username": "admin",
          "accountNonLocked": true
        },
        "details": {
          "remoteAddress": "127.0.0.1"
        }
      }
    }
    

    退出成功后,我们再请求接口 /admin/get ,发现返回JSON字符串:

    {
      "msg": "未登录或者登录失效",
      "code": 1001,
      "data": "Full authentication is required to access this resource"
    }
    

    然后我们重新登录后继续请求接口 /admin/get ,发现正常请求到数据。

    spring security系列文章请 点击这里 查看。
    这是代码 码云地址
    注意注意!!!项目是使用分支的方式来提交每次测试的代码的,请根据章节来我切换分支。

  • 相关阅读:
    leetcode33. Search in Rotated Sorted Array
    pycharm 设置sublime text3 monokai主题
    django class Meta
    leetcode30, Substring With Concatenation Of All Words
    Sublime text3修改tab键为缩进为四个空格,
    sublime text3 python打开图像的问题
    安装上imesupport输入法依然不跟随的解决办法,
    sublime text3 的插件冲突弃用问题,
    sublime text3 BracketHighlighter括号匹配的设置
    windows 下wget的使用
  • 原文地址:https://www.cnblogs.com/lixingwu/p/13291255.html
Copyright © 2011-2022 走看看