복붙노트

[SPRING] 요청 매개 변수에 기반한 Spring 보안 인증

SPRING

요청 매개 변수에 기반한 Spring 보안 인증

내가 작업하고있는 응용 프로그램은 폼 기반 인증을 처리하기 위해 이미 Spring Security를 ​​가지고 있습니다. 이제 토큰이 요청 매개 변수 중 하나에서 발견되면 외부 서비스를 통해 프로그래밍 방식으로 사용자에 로그인해야합니다.

즉, "token"과 같은 특정 요청 매개 변수가 존재하는 경우 해당 토큰이 유효한 토큰인지 확인하기 위해 해당 토큰과 함께 외부 서비스를 호출해야합니다. 그러면 사용자가 로그인하게됩니다.

Spring Security에서 "트리거"또는 "연결"하는 방법과 장소를 알아내어이 매개 변수를 확인하고 로그인 양식이 없으므로 확인을 한 다음 적절할 때 사용자를 인증 할 수 없습니다. 스프링 시큐리티에는 확장 또는 커스터마이징이 필요하다는 생각이 들었습니다.

스프링 보안 문서를 살펴본 후 AbstractPreAuthenticatedProcessingFilter가 올바른지 알아 보았습니까?

해결법

  1. ==============================

    1.내 응용 프로그램에서 비슷한 설정이 있습니다. 내가 말할 수있는 한 기본 요소는 다음과 같습니다.

    내 응용 프로그램에서 비슷한 설정이 있습니다. 내가 말할 수있는 한 기본 요소는 다음과 같습니다.

    다음과 같이 AuthenticationProvider를 만들어야합니다.

    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;
        }
    }
    

    또한 맞춤 매개 변수를 인증 토큰으로 바꾸기 위해 필터를 만들어야합니다.

    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<String,String[]> 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<? extends GrantedAuthority> getAuthorities() {
                return new ArrayList<GrantedAuthority>(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
            }
        }
    
     }
    

    다음에 대한 bean을 작성해야합니다.

    <beans:bean id="authTokenFilter" class="com.example.security.AuthenticationTokenFilter" scope="singleton" />
    <beans:bean id="tokenAuthProvider" class="com.example.security.TokenAuthenticationProvider" />
    

    마지막으로,이 빈들을 보안 설정에 연결해야합니다 (그에 따라 조정하십시오) :

    <sec:http >
       <!-- other configs here -->
       <sec:custom-filter ref="authTokenFilter" after="BASIC_AUTH_FILTER" /> <!-- or other appropriate filter -->
    </sec:http>
    
    <sec:authentication-manager>
        <!-- other configs here -->
        <sec:authentication-provider ref="tokenAuthProvider" />
    </sec:authentication-manager>
    

    또 다른 방법이있을 수 있지만 이것은 확실히 작동합니다 (현재 Spring Security 3.1 사용).

  2. ==============================

    2.Spring MVC 컨트롤러 또는 서비스를 사용하는 경우, targe 요청 파라미터가 전달 된 곳에서 @PreAuthorize Spring 보안 주석을 사용할 수있다.

    Spring MVC 컨트롤러 또는 서비스를 사용하는 경우, targe 요청 파라미터가 전달 된 곳에서 @PreAuthorize Spring 보안 주석을 사용할 수있다.

    말하자면, 전달 된 토큰을 검사하고 전달 된 토큰이 유효한 경우 인증을 수행 할 수있는 Spring 서비스가 있습니다.

    @Service("authenticator")
    class Authenticator {        
    ...
    public boolean checkTokenAndAuthenticate(Object token) {
        ...
        //check token and if it is invalid return "false"
        ...
        //if token is valid then perform programmatically authentication and return "true"  
    }
    ...             
    }    
    

    그런 다음 Spring 보안 @PreAuthorize 주석을 사용하여 다음과 같이 할 수 있습니다.

    ...
    @PreAuthorize("@authenticator.checkTokenAndAuthenticate(#token)")
    public Object methodToBeChecked(Object token) { ... }
    ...
    

    또한 스프링 보안 주석을 활성화하고 POM (또는 클래스 패스에 jar)에 스프링 보안 측면을 추가해야합니다.

  3. from https://stackoverflow.com/questions/19791406/spring-security-authentication-based-on-request-parameter by cc-by-sa and MIT license