java - 在 loadUserDetails 方法中捕获 httpServeletRequest

标签 java spring jakarta-ee spring-security

我有一个自定义的 spring AuthenticationProvider 类,但尝试在 loadUserDetails 方法中拦截 HTTPServletRequestHTTPServletResponse

@Component("darnGoodAuthenticaionProvider")
public class DarnGoodAuthenticaionProvider 
                    extends HandlerInterceptorAdapter 
                    implements AuthenticationUserDetailsService {
    private HttpServletRequest request;
    private HttpServletResponse response;

    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, Object handler) 
                            throws Exception {
            this.request = request;
            this.response = response;
            // we don't want anything falling here
            return true;
}

    @Override
    public UserDetails loadUserDetails(Authentication token)throws 
                                                    UsernameNotFoundException{
           .......
    }
}

我知道 HandlerIntercepterAdapter 中的 preHandler 方法能够完成这项工作,但我如何确定 preHandler 方法在 loadUserDetails 之前被调用,以便我可以准备好请求和响应?

谢谢

最佳答案

在 servlet 容器上,每个请求将从收到请求的那一刻开始处理,直到仅由一个线程返回响应(请求 == 当前线程)。

因此,问题是在 Spring Security 过滤器链之前放置一个 Servlet 过滤器(过滤器映射元素位于 Spring Security 的过滤器映射之上),并使用 ThreadLocal 变量将请求和响应存储在线程中 - 另请参阅此 answer .

然后在 DarnGoodAuthenticaionProvider 上使用静态方法 RequestResponseHolder.getRequest() 访问请求。

web.xml 配置:

<filter>
    <filter-name>saveRequestResponseFilter</filter-name>
    <filter-class>sample.save.request.filter.SaveRequestResponseFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>saveRequestResponseFilter</filter-name>
    <url-pattern>/mobilews/*</url-pattern>
</filter-mapping>

过滤以在线程中保存请求响应:

public class SaveRequestResponseFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        RequestResponseHolder.setRequestResponse(req,resp);
        try {
            chain.doFilter(request, response);
        }
        finally {
            RequestResponseHolder.clear();
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        ...
    }

    @Override
    public void destroy() {
       ...
    }
}

请求/响应持有者:

public class RequestResponseHolder {

    private static ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<HttpServletRequest>();
    private static ThreadLocal<HttpServletResponse> responseHolder = new ThreadLocal<HttpServletResponse>();


    public static void setRequestResponse(HttpServletRequest request, HttpServletResponse response) {
        requestHolder.set(request);
        responseHolder.set(response);
    }

    public static HttpServletRequest getServletRequest(){
         return requestHolder.get();
    }

    public static HttpServletResponse getServletResponse()  {
        return responseHolder.get();
    }

    public static void clear() {
        requestHolder.remove();
        responseHolder.remove();
    }
}

DarnGoodAuthenticaionProvider 获取请求:

HttpServletRequest req = RequestResponseHolder.getServletRequest();

关于java - 在 loadUserDetails 方法中捕获 httpServeletRequest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21123852/

相关文章:

java - 如何在 ganymed-ssh2-build210.jar 中禁用 diffie-hellman-group1-sha1

java - 错误无法加载资源: the server responded with a status of 403 () en angular

java - 对文件系统中的文件夹执行命令

java - 覆盖 YAML 中的属性

java - 无需 session 的身份验证、授权和用户跟踪

java - 如何快速将表达式转换为空检查?

java - Spring Data - 按类型进行继承搜索

java - 暂时禁用 Spring Security (ldap auth)

java - SAX 解析器具有相似的父标签和子标签

java - 如何在 Java EE 和 Spring Boot 中热重载属性?