Spring 中的混乱 Spring 引导中的安全性
Confusion In Spring Security in Spring Boot
我有一个自定义 UserDetailService
实现程序,即 MyCustomUserDetailService
其中 loadUserByName 方法被覆盖。
我有生成 JWT 令牌的令牌生成器 class。
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
"?
我知道这个问题有点冗长,但作为一个初学者,我正在努力理解它背后的机制,并且我已经对其进行了研究,但这种困惑并没有消失。请帮忙。另外,如果您认为问题有误,请建议我如何简明我的问题。
UsernamePasswordAuthenticationToken
中的详细信息完全取决于您,如果您稍后在应用程序中需要来自经过身份验证的用户的更多详细信息,它会有所帮助。就像您调用 SecurityContextHolder.getContext().getAuthentication()
一样,您可以将此 Authentication
转换为 UsernamePasswordAuthenticationToken
并出于任何商业目的访问其详细信息;
您的 UsernamePasswordAuthenticationToken
未针对任何内容进行验证,您需要通过调用 UserDetailsService
并检查密码或注入并调用 [=17] 来手动执行此操作=] 方法。 Spring 安全性 does not care 如何填充 SecurityContextHolder
。在基本场景中,将经过身份验证的 SecurityContext
设置为 SecurityContextHolder
后,SecurityContextPersistenceFilter
会将此 SecurityContext
作为属性保存在 HttpSession
中。
在接下来的请求中,此属性将出现在您的 HttpSession
中,这样 Spring 安全加载 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 安全性的工作原理。还有一个 reference documentation 是了解更多架构细节的重要来源。
我有一个自定义 UserDetailService
实现程序,即 MyCustomUserDetailService
其中 loadUserByName 方法被覆盖。
我有生成 JWT 令牌的令牌生成器 class。
I have a class called
JWTAuthenticationFilter
that extendsOnceperRequestFilter
where there is adoFilter
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 inUsernamePasswordAuthenticationToken
.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 ofUsernamePasswordAuthenticationToken
but against what it is validating "upat"? IsUsernamePasswordAuthenticationToken
automatically internally checking with the "MyCustomUserDetailService
"?
我知道这个问题有点冗长,但作为一个初学者,我正在努力理解它背后的机制,并且我已经对其进行了研究,但这种困惑并没有消失。请帮忙。另外,如果您认为问题有误,请建议我如何简明我的问题。
UsernamePasswordAuthenticationToken
中的详细信息完全取决于您,如果您稍后在应用程序中需要来自经过身份验证的用户的更多详细信息,它会有所帮助。就像您调用SecurityContextHolder.getContext().getAuthentication()
一样,您可以将此Authentication
转换为UsernamePasswordAuthenticationToken
并出于任何商业目的访问其详细信息;您的
UsernamePasswordAuthenticationToken
未针对任何内容进行验证,您需要通过调用UserDetailsService
并检查密码或注入并调用 [=17] 来手动执行此操作=] 方法。 Spring 安全性 does not care 如何填充SecurityContextHolder
。在基本场景中,将经过身份验证的SecurityContext
设置为SecurityContextHolder
后,SecurityContextPersistenceFilter
会将此SecurityContext
作为属性保存在HttpSession
中。 在接下来的请求中,此属性将出现在您的HttpSession
中,这样 Spring 安全加载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 安全性的工作原理。还有一个 reference documentation 是了解更多架构细节的重要来源。