解决Spring cloud 整合security,token过期以后跳转默认登录页的问题

2023-01-18 18:56:14

解决Spring security token过期以后跳转默认登录页的问题

1、背景

因为启动新项目,用到了spring security的架构。新项目是一个前后端分离的项目,但是整合进来以后,登录没有问题,但是只要401,就会弹出spring security的默认登录页。如下图
在这里插入图片描述

排查过程

试过很多方式,比方:禁用formLogin(),禁用httpBasic都没有用,包括在@SpringBootApplication注解上加(exclude = {SecurityAutoConfiguration.class})也不行。谷歌百度的方法大多都试过了,找不到合适的解决办法。
后来突然想到项目中的security引入是借鉴的码云的一个大佬的项目,就想试试看别人的项目会不会也这样,结果跑起来发现并不会。这样就找到解决的方向了,一定是配置出现了什么问题。所以就在一切在401可能访问到的过滤器上打断点,然后和自己项目对比,终于发现了区别。是自定义继承HttpBasicServerAuthenticationEntryPoint的类有区别
码云大佬地址:https://gitee.com/AloneH/spring-security_springcloud-gateway.git

package com.vdpub.auth.security.webflux.handler;

import com.vdpub.auth.security.webflux.utils.ResponseUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.server.authentication.HttpBasicServerAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @description: 自定义token验证失败处理逻辑
 *  *                  1、token验证失败的处理逻辑(token为空,或者过期时)
 *  *                  2、设置响应头
 *  *                  3、写入响应内容
 * @author: Max
 * @create: 2021-03-05 17:53
 **/
@Component
public class CustomHttpBasicServerAuthenticationEntryPoint extends HttpBasicServerAuthenticationEntryPoint /* implements ServerAuthenticationEntryPoint */{


    /**新的定义*/
    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
    private static final String DEFAULT_REALM = "Realm";
    private static final String WWW_AUTHENTICATE_FORMAT = "Basic %s"; // 区别所在

    
    /**原定义***/
//    private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
//    private static final String DEFAULT_REALM = "Realm";
//    private static String WWW_AUTHENTICATE_FORMAT = "Basic realm=\"%s\""; // 区别所在
    
    private final String headerValue = createHeaderValue(DEFAULT_REALM);
    public CustomHttpBasicServerAuthenticationEntryPoint() {
    }

    /**
     * 创建错误响应头中的Authenticate
     * @param realm
     * @return
     */
    private static String createHeaderValue(String realm) {
        Assert.notNull(realm, "realm cannot be null");
        return String.format(WWW_AUTHENTICATE_FORMAT, realm);
    }


    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
        ServerHttpResponse response = exchange.getResponse();
        // 设置响应头
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().set(WWW_AUTHENTICATE, this.headerValue);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
        // 三设置 验证异常返回信息
        String responseBodyString = ResponseUtil.getResponse(e.getMessage(), HttpStatus.UNAUTHORIZED);
        byte[] responseBodyBytes = responseBodyString.getBytes();
        // 写入信息
        return response.writeWith(Mono.just(response.bufferFactory().wrap(responseBodyBytes)));
    }
}

解决办法

既然发现了是这里的区别,就直接进行了替换,将上述贴的代码中注释中的原定义内容换成新定义的内容即可。
主要是请求头的问题,换完以后,请求头由图一变为图二
图一:
在这里插入图片描述
图二:
在这里插入图片描述

至此问题解决,欢迎大家有问题一起讨论。不对地方也请大家指出、
转载请注明出处

  • 作者:桑卒想打门修斯
  • 原文链接:https://blog.csdn.net/qq_37611096/article/details/117228310
    更新时间:2023-01-18 18:56:14