Spring Security has the assumption of Authentication is a Principal.
public interface Authentication extends Principal, Serializable {}
HttpServletRequest has the method of getUserPrincipal which is responsible for accessing principal object.
Let's consider this case:
public interface RealPrincipal extends Principal {
public Integer getId();
}
Common Module A has Real Principal interface and implementation.
Module A uses Common Module A, Servlet Api and does not depend on Spring Security:
Module B uses Common Module A, Servlet Api and configures Spring Security. This module responsible for security and UserDetails implementation.
Web A uses Module A and Module B.
In order to use request methods, I am ending up with such an implementation:
public ModelAndView someRequestHandler(Principal principal) {
User activeUser = (User) ((Authentication) principal).getPrincipal();
...
}
This is forcing me to have dependency of Spring Security for the Module A and other modules. I believe that a proper servlet api abstraction should not depend on spring security. request.getUserPrincipal should return real principal.
Please explain why org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper returns
Authentication instead of Real Principal
.
Edit: I have added Common Module A to my scenario and updated that Module B is responsible for security.
As Luke stated, Spring Security uses the Authentication for the Principal because it implements Principal. It does not use the Authentication#getPrincipal() because it is not guaranteed to be a Principal (it is an Object). In fact, in most situations Spring Security's Authentication#getPrincipal() returns a User (does not implement Principal), a custom UserDetails provided by users of the framework, or a String.
If you want Spring Security to handle this, you will likely need to implement this logic using an HttpServletRequestWrapper as Luke suggested. For example, you could do the following:
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);
}
...
}
Alternatively, take a look at my answer on your other question for options to integrate with Spring MVC - Injecting Custom Principal to Controllers by Spring Security
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With