Spring Security假设Authentication是Principal。
public interface Authentication extends Principal, Serializable {}
HttpServletRequest的方法为getUserPrincipal,负责访问主体对象。
让我们考虑一下这个案例:
public interface RealPrincipal extends Principal {
public Integer getId();
}
通用模块A具有Real Principal接口和实现。
模块A使用Common Module A,Servlet Api并且不依赖于Spring Security:
模块B使用Common Module A,Servlet Api并配置Spring Security。该模块负责安全性和UserDetails的实现。
Web A使用模块A和模块B.
为了使用请求方法,我最终得到了这样的实现:
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
这迫使我对模块A和其他模块依赖Spring Security。我认为适当的servlet api抽象不应该依赖于spring安全性。 request.getUserPrincipal应返回真实主体。
请解释为什么org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper返回
身份验证而不是Real Principal
。
编辑:我已在我的方案中添加了通用模块A,并更新了模块B负责安全性。
答案 0 :(得分:3)
正如Luke所说,Spring Security使用Principal身份验证,因为它实现了Principal。它不使用Authentication#getPrincipal(),因为它不能保证是Principal(它是一个Object)。事实上,在大多数情况下,Spring Security的Authentication#getPrincipal()返回一个User(不实现Principal),框架用户提供的自定义UserDetails或String。
如果你想让Spring Security处理这个问题,你可能需要使用HttpServletRequestWrapper来实现这个逻辑,正如Luke建议的那样。例如,您可以执行以下操作:
public RealPrincipalFilter extends OncePerRequestFilter {
public void doFiter(HttpServletRequest request, HttpServletResponse response, FilterChain) {
chain.doFilter(new RealPrincipalRequestWrapper(request), response);
}
private static final class RealPrincipalRequestWrapper
extends HttpServletRequestWrapper {
public Principal getUserPrincipal() {
Authentication auth = (Authentication) super.getPrincipal();
return auth == null ? null : (RealPrincipal) auth.getPrincipal()
}
}
}
@Configuration
@EnableWebSecurity
public WebSecurityConfig extends WebSecurityConfigurerAdapter {
public configure(HttpSecurity http) {
http
// ... other config ...
.addFilterAfter(new RealPrincipalFilter(), SecurityContextHolderAwareRequestFilter.class);
}
...
}
或者,看看我对你的另一个问题的答案,了解与Spring MVC集成的选项 - Injecting Custom Principal to Controllers by Spring Security
答案 1 :(得分:1)
简短的回答是Authentication
是Principal
,因此可以在需要的API(例如您提到的servlet API方法)中使用它。
这在实践中意味着什么?不是很多。 Java的Principal
接口只有一个方法getName
,所以如果你想做的不仅仅是渲染用户名,你还需要了解更多关于实现的信息。
当您使用短语“真实主体”和“正确的servlet api抽象”时,您应该考虑一下您的意思。例如,如果委托人是“真正的”主体,您期望如何实施someRequestHandler
方法?