I set principal=jack in MyAuthenticationFilter, and reset principal=jackLee in MyAuthenticationProvider. Finally, I get jack by @AuthenticationPrincipal.

the code download url: https://github.com/weitangli/spring-security-principal.git

public class MyAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String principal = "jack";
        String credentials = "abc123";

        PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(principal, credentials);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);
    }
}
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String principal = "jackLee";
        String credentials = "abc123";
        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_ADMIN");

        PreAuthenticatedAuthenticationToken result = new PreAuthenticatedAuthenticationToken(principal, credentials, authorities);
        return result;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterAt(preAuthenticatedAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class);

        http.csrf().disable();
        http.requestCache().disable();
    }

    public MyAuthenticationFilter preAuthenticatedAuthenticationFilter() {
        MyAuthenticationFilter authenticationFilter = new MyAuthenticationFilter();
        return authenticationFilter;
    }
}
@RestController
public class HelloController {

    @Secured("ROLE_ADMIN")
    @GetMapping("/hello")
    public String hello(@AuthenticationPrincipal String principal) {
        String authenticatedPrincipal = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return "Hello " + principal + ", and authenticated principal is " + authenticatedPrincipal;
    }
}

Comment From: eleftherias

Thanks for providing a sample @weitangli.

The strange behaviour that you are seeing is caused by using classes in way that they are not intended.

Let's take a look at the custom Filter, MyAuthenticationFilter. MyAuthenticationFilter is setting the authentication to an instance of PreAuthenticatedAuthenticationToken. PreAuthenticatedAuthenticationToken is not a fully populated Authentication object. It does not include granted authorities and it will return false from the method isAuthenticated(). This object should not be set in the SecurityContext.

Instead, if the request is pre-authenticated (the principal has already been authenticated by an external system), then the custom filter MyAuthenticationFilter could extend AbstractPreAuthenticatedProcessingFilter.

public class MyAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {

    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        return "jack";
    }

    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
        return "abc123";
    }
}

This filter is typically used in combination with a PreAuthenticatedAuthenticationProvider, which is used to load additional data for the user.

If the request is not pre-authenticated, consider using a different implementation of AbstractAuthenticationToken, that is fully populated. Depending on your use case, you may find an existing implementation that is suitable, for example UsernamePasswordAuthenticationToken, or you may create your own implementation.

This is what MyAuthenticationFilter would look like if you use UsernamePasswordAuthenticationToken.

public class MyAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String principal = "jack";
        String credentials = "abc123";

        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(principal, credentials);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);
    }
}

I am going to close this issue, but feel free to post any follow up questions below.