首页 > 其他分享 >七、注销

七、注销

时间:2023-06-08 22:22:57浏览次数:25  
标签:return LOGIN PAGE logout new 注销 public

一、使用logout

修改MyReactiveSecurityConfig:

@Configuration
@Slf4j
public class MyReactiveSecurityConfig {
    @Autowired
    private ReactiveUserDetailsService reactiveUserDetailsService;

    @Autowired(required = false)
    private ReactiveUserDetailsPasswordService userDetailsPasswordService;


    private final static String LOGIN_PAGE="/doLogin";

//    @Bean
//    public ReactiveUserDetailsService reactiveUserDetailsService() {
//        UserDetails user = User.withUsername("user")
//                .password("12345")
//                .roles("USER")
//                .build();
//        return new MapReactiveUserDetailsService(user);
//    }

//    @Bean
//    public PasswordEncoder passwordEncoder() {
//        return NoOpPasswordEncoder.getInstance();
//    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .authorizeExchange(exchanges -> exchanges
                        .pathMatchers(LOGIN_PAGE).permitAll()
                        .pathMatchers("/verify_code").permitAll()
                        .anyExchange().authenticated()
                )
                .formLogin()
                .loginPage(LOGIN_PAGE)
                .and()
               // .loginPage(LOGIN_PAGE)
              //  .and()
                .csrf().disable()
                .logout();

        http.addFilterAt(authenticationManager(), SecurityWebFiltersOrder.FORM_LOGIN);
        return http.build();
    }


    @Bean
    public ReactiveAuthenticationManager userDetailsRepositoryReactiveAuthenticationManager() {
        UserDetailsRepositoryReactiveAuthenticationManager manager = new UserDetailsRepositoryReactiveAuthenticationManager(this.reactiveUserDetailsService);
        manager.setPasswordEncoder(passwordEncoder());
        manager.setUserDetailsPasswordService(this.userDetailsPasswordService);
        return manager;
    }


    @Bean
    public AuthenticationWebFilter authenticationManager() {
        AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(userDetailsRepositoryReactiveAuthenticationManager());
        authenticationFilter.setRequiresAuthenticationMatcher(ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, LOGIN_PAGE));
        authenticationFilter.setAuthenticationFailureHandler(new RedirectServerAuthenticationFailureHandler(LOGIN_PAGE + "?error"));
        authenticationFilter.setAuthenticationConverter(new KaptchServerAuthenticationConverter());
        authenticationFilter.setAuthenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/"));
        authenticationFilter.setSecurityContextRepository(new WebSessionServerSecurityContextRepository());
        return authenticationFilter;
    }
}

增加了注销配置。

 

用postman模拟登录后。在访问注销接口:    

注销成功后,重定向到登录页面。

 

还可以增加logoutSuccessHandler注销成功后返回json格式数据:

    @Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http
            .authorizeExchange(exchanges -> exchanges
                    .pathMatchers(LOGIN_PAGE).permitAll()
                    .pathMatchers("/verify_code").permitAll()
                    .anyExchange().authenticated()
            )
            .formLogin()
            .loginPage(LOGIN_PAGE)
            .and()
           // .loginPage(LOGIN_PAGE)
          //  .and()
            .csrf().disable()
            .logout()
            .logoutSuccessHandler(((webFilterExchange, authentication) -> {
                ServerWebExchange exchange = webFilterExchange.getExchange();
                exchange.getResponse().getHeaders().add("Content-type", MediaType.APPLICATION_JSON_UTF8_VALUE);
                    Flux<DataBuffer> dataBufferFlux = DataBufferUtils.read(new ByteArrayResource("注销成功".getBytes(StandardCharsets.UTF_8)), exchange.getResponse().bufferFactory(), 1024 * 8);

                    return exchange.getResponse().writeAndFlushWith(t -> {
                        t.onSubscribe(new Subscription() {
                            @Override
                            public void request(long l) {

                            }
                            @Override
                            public void cancel() {

                            }
                        });
                        t.onNext(dataBufferFlux);
                        t.onComplete();
                    });
            }));

    http.addFilterAt(authenticationManager(), SecurityWebFiltersOrder.FORM_LOGIN);
    return http.build();
}

访问注销接口:    

二、源码分析

注销操作由LogoutWebFilter过滤器处理。

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
	return this.requiresLogout.matches(exchange).filter((result) -> result.isMatch())
			.switchIfEmpty(chain.filter(exchange).then(Mono.empty())).map((result) -> exchange)
			.flatMap(this::flatMapAuthentication).flatMap((authentication) -> {
				WebFilterExchange webFilterExchange = new WebFilterExchange(exchange, chain);
				return logout(webFilterExchange, authentication);
			});
}

requiresLogout匹配以POST方法访问的/logout路径请求。调用flatMapAuthentication从ServerWebExchange获取Authentication。如果获取不到则设置匿名用户anonymousAuthenticationToken:

	private AnonymousAuthenticationToken anonymousAuthenticationToken = new AnonymousAuthenticationToken("key",
		"anonymous", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));

最后调用logout处理注销操作。

 

private Mono<Void> logout(WebFilterExchange webFilterExchange, Authentication authentication) {
	logger.debug(LogMessage.format("Logging out user '%s' and transferring to logout destination", authentication));
	return this.logoutHandler.logout(webFilterExchange, authentication)
			.then(this.logoutSuccessHandler.onLogoutSuccess(webFilterExchange, authentication))
			.subscriberContext(ReactiveSecurityContextHolder.clearContext());
}

logoutHandler默认是SecurityContextServerLogoutHandler,SecurityContextServerLogoutHandler会将SecurityContext从WebSession中移除。logoutSuccessHandler默认重定向到/login?logout

 

这里有个问题,重新配置登录页面了,但是LogoutWebFilter没有修改注销后重定向的url,还是/login?logout,为什么注销后还能重定向到自定义的登录页?

因为有ExceptionTranslationWebFilter。重新配置登录页后,/login?logout没有开放访问权限,重定向到/login?logout会发生AccessDeniedException异常,同时Authentication被LogoutWebFilter清楚了,所以由ExceptionTranslationWebFilter的authenticationEntryPoint处理,在配置登录页面时,重设置了authenticationEntryPoint的重定向url。最终会重定向到自定义的登录页。

 

修改:

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http
            .authorizeExchange(exchanges -> exchanges
                    .pathMatchers(LOGIN_PAGE).permitAll()
                    .pathMatchers("/verify_code").permitAll()
                    .pathMatchers("/login").permitAll()
                    .anyExchange().authenticated()
            )
            .formLogin()
            .loginPage(LOGIN_PAGE)
            .and()
           // .loginPage(LOGIN_PAGE)
          //  .and()
            .csrf().disable()
            .logout()
            ;

    http.addFilterAt(authenticationManager(), SecurityWebFiltersOrder.FORM_LOGIN);
    return http.build();
}

重新访问注销,发现出现404。

标签:return,LOGIN,PAGE,logout,new,注销,public
From: https://www.cnblogs.com/shigongp/p/17467747.html

相关文章

  • Qt+QtWebApp开发笔记(四):http服务器使用Session和Cookie实现用户密码登录和注销功能
    前言  前面实现了基础的跳转,那么动态交互中登录是常用功能。  本篇实现一个动态交互的简单登录和注销功能,在Qt中使用Session和Cookie技术。 Demo  下载地址  链接:https://pan.baidu.com/s/1nkmsHgr-11Khe9k6Ntyf_g?pwd=1234 Html处理用户输入Sessi......
  • 实现在线用户列表显示、注销的Listener
    实现在线用户列表显示、注销的Listener文章分类:Java编程实现一个对在线用户的监听:即监听用户的登录和注销两个操作。需要自定义一个Listener,实现ServletContextListener,HttpSessionListener和HttpSessionAttributeListener。一、表示层:1、用户登录表单Login.jspJsp......
  • springsecurity 认证,授权,注销,动态菜单,记住我和首页定制
    搭建环境:1.在创建springboot时选择组件web,thymeleaf,spring-security2.导入静态资源,导入后测试一下环境 认证和授权:继承类WebSecurityConfigurerAdapter,重写方法configure若遇到报错:java.lang.IllegalArgumentException:ThereisnoPasswordEncodermappedfortheid"nu......
  • 认证失败处理器与注销成功处理器
    认证失败处理器  packagecom.example.springsecurity.handler;importorg.springframework.security.core.AuthenticationException;importorg.springframework.security.web.authentication.AuthenticationFailureHandler;importorg.springframework.ste......
  • 第 7 -8章 Linux 实操篇-开机、重启和用户登录注销-8.用户管理
    第7-8章Linux实操篇-开机、重启和用户登录注销-8.用户管理目录第7-8章Linux实操篇-开机、重启和用户登录注销-8.用户管理7.1关机&重启命令7.1.1基本介绍7.1.2注意细节7.2用户登录和注销7.2.1基本介绍7.2.2使用细节第8章Linux实操篇-用户管理8.1基本介绍8.2添......
  • 009.关机 重启 注销
    关机重启注销shutdown-hnow立即进行关机shutdown-h11分钟后进行关机shutdown-rnow立即重新启动计算机halt关机reboot现在重新启动计算机sync把内存数据同步到磁盘su-root切换到系统管......
  • flask,mysql实现用户登录注册注销改密
    flask.py文件fromflaskimportFlask,render_template,request,redirect,url_for,flash,sessionfromflask_mysqldbimportMySQLimportbcryptapp=Flask(__name__)app.secret_key="secret"#MySQLconfigurationsapp.config['MYSQL_HOST'......
  • 在linux操作系统下注销、关机、重启的简单命令
    一、注销的命令——Logout是登陆的相对操作,登陆系统后,若要离开系统,用户只要直接下达logout命令即可:#logout二、关机或重新启动的命令——shutd......
  • 2.注销带ACL TOKEN的服务
    acl.json{ "datacenter":"dc1", "acl":{ "enabled":true, "default_policy":"deny", "down_policy":"extend-cache", "tokens":{ ......
  • 在Linux中如何注销其他 SSH 用户
    如果你通过ssh登录了一个远程Linux系统,只需要使用exit 命令即可退出ssh。那么,如果你想要注销其他通过ssh登录到系统中的用户呢?在ssh会话中注销用户首先,检查L......