spring-boot - Spring Boot 中 Spring Security 的困惑

标签 spring-boot spring-security

我有一个自定义的UserDetailService实现器,即MyCustomUserDetailService,其中loadUserByName方法被重写。

我有生成 JWT token 的 token 生成器类。

I have a class called JWTAuthenticationFilter that extends OnceperRequestFilter where there is a doFilter method where I am validating the token that has been generated and provided by the client in the header of the HttpRequest. Now from here is my real question starts. The code is something like this:

UserDetails usd=this.myCustomUserDetailService.loadByUserName(userNameFromToke);//userNameFromToke is a String that got extracted from the token that client provided.

UsernamePasswordAuthenticationToken upat=new UsernamePasswordAuthenticationToken(usd,null,usd.getAuthorities()); //Here in the password I am passing null.

upat.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));

SecurityContextHolder.getContext().setAuthentication(upat);

Question 1:

`ups.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));`

why we are passing the whole HTTP Request(i.e.httpRequest) rather than the userdetails that we extracted from the token? And why do I need this setDetails method as I have already passed the userdetails,pasword and the list of authorities in the constructor argument in UsernamePasswordAuthenticationToken.

Question 2:

How is the setAuthentication method and UsernamePasswordAuthenticationToken working? I am passing the information that I have extracted from the token i.e. SecurityContextHolder.getContext().setAuthentication(upat); and userdetails,passowords and authorities in the constructor of UsernamePasswordAuthenticationToken but against what it is validating "upat"? Is UsernamePasswordAuthenticationToken automatically internally checking with the "MyCustomUserDetailService"?

我知道这个问题有点长,但由于我是初学者,我正在努力理解其背后的机制,并且我已经对其进行了研究,但这种困惑并没有消失。请帮忙。另外,如果您认为我的问题有问题,请建议我如何简洁地表达我的问题。

最佳答案

  1. UsernamePasswordAuthenticationToken 中的详细信息完全取决于您,如果您稍后在应用程序中需要来自经过身份验证的用户的更多详细信息,它会有所帮助。就像调用 SecurityContextHolder.getContext().getAuthentication() 时一样,您可以将此 Authentication 强制转换为 UsernamePasswordAuthenticationToken 并出于任何业务目的访问其详细信息;

  2. 您的 UsernamePasswordAuthenticationToken 未针对任何内容进行验证,您需要通过调用 UserDetailsS​​ervice 并检查密码,或者注入(inject)并调用 AuthenticationManager#authenticate 方法。 Spring 安全does not care如何填充SecurityContextHolder。在基本场景中,将经过身份验证的 SecurityContext 设置到 SecurityContextHolder 中后,SecurityContextPersistenceFilter 将获取此 SecurityContext 并保存它在 HttpSession 中作为属性。 在接下来的请求中,此属性将出现在您的 HttpSession 中,这样 Spring Security 会加载 SecurityContext 并将其设置到 SecurityContextHolder 中。

您可以在SecurityContextPersistenceFilter implementation中获取更多详细信息,但我会在这里指出这个问题的具体部分:

HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
// Here Spring Security loads the SecurityContext from the HttpSession, this is done before reaching your controllers, before calling the FilterChain.
SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder); 
try {
    SecurityContextHolder.setContext(contextBeforeChainExecution);
    if (contextBeforeChainExecution.getAuthentication() == null) {
        logger.debug("Set SecurityContextHolder to empty SecurityContext");
    }
    else {
        if (this.logger.isDebugEnabled()) {
            this.logger
                        .debug(LogMessage.format("Set SecurityContextHolder to %s", contextBeforeChainExecution));
        }
    }
    chain.doFilter(holder.getRequest(), holder.getResponse());
}
finally {
    // You've populated the SecurityContextHolder and it'll be available here after you application returns. So it'll get the SecurityContext and persist it in the HttpSession
    SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
    SecurityContextHolder.clearContext();
    // Persisting the SecurityContext in the HttpSession
    this.repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
    request.removeAttribute(FILTER_APPLIED);
    this.logger.debug("Cleared SecurityContextHolder to complete request");
}

我希望这可以帮助您更好地理解 Spring Security 的工作原理。还有一个reference documentation这是了解更多架构细节的重要来源。

关于spring-boot - Spring Boot 中 Spring Security 的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68113942/

相关文章:

java - Angular 6 和 spring boot 通过基于 session 的登录记住我

java - 在 spring Controller 中处理一些自定义验证

spring-mvc - 您如何保护 SpringBoot/Spring-Data Rest 以便用户只能访问他自己的实体

java - Spring Oauth 异常消息中的国际化

spring-mvc - 无法使用 Spring Security 创建 CSRF token

java - Spring-Retry 断路器会移动以恢复代码,在出现异常时无需任何重试尝试

java - Spring 安全访问控制允许来源 : * (CORS) issue on invalid JWT token

java - 通过 main 的命令行参数传递 Active Profile

grails - 交易管理器的GrailsContextLoader错误

java - 无法解析 Spring Boot 应用程序中的符号 "security"