Spring Boot中Spring安全性的困惑

5t7ly7z5  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(302)

我有一个习惯 UserDetailService 实施者,即。 MyCustomUserDetailService 其中loaduserbyname方法被重写。
我有一个生成jwt令牌的令牌生成器类。
我有一门课叫 JWTAuthenticationFilter 延伸 OnceperRequestFilter 哪里有 doFilter 方法,其中我正在验证客户端在httprequest头中生成和提供的令牌。现在我真正的问题从这里开始。代码如下所示:

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);

问题1:

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

为什么我们要传递整个http请求(即httprequest),而不是从令牌中提取的userdetails?为什么我需要这个 setDetails 方法,因为我已经在中的构造函数参数中传递了userdetails、pasword和权限列表 UsernamePasswordAuthenticationToken .
问题2:
setauthentication方法和usernamepasswordauthenticationtoken如何工作?我正在传递我从令牌中提取的信息,即。 SecurityContextHolder.getContext().setAuthentication(upat) ; 以及的构造函数中的用户详细信息、密码和权限 UsernamePasswordAuthenticationToken 但与它正在验证的“upat”相反?是 UsernamePasswordAuthenticationToken 自动在内部检查“ MyCustomUserDetailService "?
我知道这个问题有点长,但作为一个初学者,我正在努力理解它背后的机制,我已经做了研究,但这种困惑并没有消失。请帮忙。另外,如果你认为我的问题有缺陷,建议我如何精简我的问题。

n9vozmp4

n9vozmp41#

详情见 UsernamePasswordAuthenticationToken 这完全取决于您,如果您以后在应用程序中需要来自已验证用户的更多详细信息,它会有所帮助。比如你打电话的时候 SecurityContextHolder.getContext().getAuthentication() ,你可以投这个 AuthenticationUsernamePasswordAuthenticationToken 并出于任何商业目的访问其详细信息;
你的 UsernamePasswordAuthenticationToken 没有针对任何内容进行验证,您需要通过调用 UserDetailsService 检查密码,或者打电话 AuthenticationManager#authenticate 方法。spring security不关心 SecurityContextHolder 人口众多。在基本场景中,在设置经过身份验证的 SecurityContext 进入 SecurityContextHolder 这个 SecurityContextPersistenceFilter 我要这个 SecurityContext 并保存在 HttpSession 作为一种属性。在接下来的请求中,此属性将出现在 HttpSession ,这样spring security将加载 SecurityContext 并将其设置为 SecurityContextHolder .
您可以在 SecurityContextPersistenceFilter 实现,但我将在这里指出这个问题的具体部分:

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 是如何工作的。还有一个参考文档,它是了解更多架构细节的好来源。

相关问题