Spring security authentication based on request parameter

前端 未结 2 703
盖世英雄少女心
盖世英雄少女心 2020-12-13 16:06

The application I\'m working on already has Spring Security to handle form based authentication. Now the requirement is to login a user programmatically via an external serv

2条回答
  •  -上瘾入骨i
    2020-12-13 16:54

    I have a similar setup in my application. Here are the basic elements as far as I can tell:

    You need to create an AuthenticationProvider like so:

    public class TokenAuthenticationProvider implements AuthenticationProvider {
    
        @Autowired private SomeService userSvc;
    
        @Override
        public Authentication authenticate(Authentication auth) throws AuthenticationException {
            if (auth.isAuthenticated())
                return auth;
    
            String token = auth.getCredentials().toString();
            User user = userSvc.validateApiAuthenticationToken(token);
            if (user != null) {
                auth = new PreAuthenticatedAuthenticationToken(user, token);
                auth.setAuthenticated(true);
                logger.debug("Token authentication. Token: " + token + "; user: " + user.getDisplayName());
            } else
                throw new BadCredentialsException("Invalid token " + token);
            return auth;
        }
    }
    

    You also need to create a Filter to turn the custom parameter into an authentication token:

    public class AuthenticationTokenFilter implements Filter {
    
    
        @Override
        public void init(FilterConfig fc) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
            SecurityContext context = SecurityContextHolder.getContext();
            if (context.getAuthentication() != null && context.getAuthentication().isAuthenticated()) {
                // do nothing
            } else {
                Map params = req.getParameterMap();
                if (!params.isEmpty() && params.containsKey("auth_token")) {
                    String token = params.get("auth_token")[0];
                    if (token != null) {
                        Authentication auth = new TokenAuthentication(token);
                        SecurityContextHolder.getContext().setAuthentication(auth);
                    }
                }
            }
    
            fc.doFilter(req, res);
        }
    
        @Override
        public void destroy() {
    
        }
    
        class TokenAuthentication implements Authentication {
            private String token;
            private TokenAuthentication(String token) {
                this.token = token;
            }
            @Override
            public Collection getAuthorities() {
                return new ArrayList(0);
            }
            @Override
            public Object getCredentials() {
                return token;
            }
            @Override
            public Object getDetails() {
                return null;
            }
            @Override
            public Object getPrincipal() {
                return null;
            }
            @Override
            public boolean isAuthenticated() {
                return false;
            }
            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
            }
            @Override
            public String getName() {
                // your custom logic here
            }
        }
    
     }
    

    You need to create beans for these:

    
    
    

    Finally, you need to wire these beans into your security config (adjust accordingly):

    
       
        
    
    
    
        
        
    
    

    There might be another way, but this definitely works (using Spring Security 3.1 at the moment).

提交回复
热议问题