Spring을 통한 RESTful 인증

문제:
우리는 Spring MVC 기반의 RESTful API를 가지고 있으며, 여기에는 중요한 정보가 포함되어 있습니다. API는 보안되어야 하지만 각 요청과 함께 사용자의 자격 증명(사용자/패스 콤보)을 보내는 것은 바람직하지 않습니다. REST 지침(및 내부 비즈니스 요구 사항)에 따라 서버는 상태 비저장 상태를 유지해야 합니다. API는 매시업 스타일의 접근 방식으로 다른 서버에 의해 소비됩니다.

요구 사항:

  • 클라이언트는 자격 증명을 사용하여 '.../authenticate'(보호되지 않은 URL)에 요청을 하고, 서버는 서버가 향후 요청을 검증하고 상태 비저장 상태를 유지할 수 있는 충분한 정보를 포함하는 보안 토큰을 반환합니다. 이는 Spring Security'의 [Remember-Me Token][1]과 동일한 정보로 구성될 수 있습니다.

  • 클라이언트는 이전에 얻은 토큰을 쿼리 매개 변수(또는 덜 바람직하게는 HTTP 요청 헤더)로 추가하여 다양한 (보호된) URL에 후속 요청을 합니다.

  • 클라이언트에서 쿠키를 저장할 수 없습니다.

  • 우리는 이미 Spring을 사용하고 있기 때문에 솔루션은 Spring Security를 사용해야 합니다.

우리는 이 문제를 해결하려고 머리를 벽에 부딪혀 왔기 때문에 누군가 이미 이 문제를 해결했기를 바란다.

위의 시나리오를 고려할 때, 이 특정한 요구를 어떻게 해결할 수 있습니까?

[1]http://static.springsource.org/spring-security/site/docs/3.1.x/reference/remember-me.html

질문에 대한 의견 (8)
해결책

우리는 OP에 설명된 대로 정확히 이 작업을 수행할 수 있었습니다. 그리고 바라건대 다른 누군가가 솔루션을 사용할 수 있기를 바랍니다. 우리가 한 일은 다음과 같습니다.

다음과 같이 보안 컨텍스트를 설정합니다.











보시는 바와 같이 사용자 지정 인증 엔트리 포인트를 만들었습니다. 인증에 의해 필터 체인에서 인증되지 않은 경우 기본적으로 "401 Unauthorized"만 반환됩니다.토큰 처리 필터'입니다.

사용자 정의인증 진입점:

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Authentication token was either missing or invalid." );
    }
}

인증토큰 처리 필터:

public class AuthenticationTokenProcessingFilter extends GenericFilterBean {

    @Autowired UserService userService;
    @Autowired TokenUtils tokenUtils;
    AuthenticationManager authManager;

    public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) {
        this.authManager = authManager;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        @SuppressWarnings("unchecked")
        Map parms = request.getParameterMap();

        if(parms.containsKey("token")) {
            String token = parms.get("token")[0]; // grab the first "token" parameter

            // validate the token
            if (tokenUtils.validate(token)) {
                // determine the user based on the (already validated) token
                UserDetails userDetails = tokenUtils.getUserFromToken(token);
                // build an Authentication object with the user's info
                UsernamePasswordAuthenticationToken authentication = 
                        new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) request));
                // set the authentication into the SecurityContext
                SecurityContextHolder.getContext().setAuthentication(authManager.authenticate(authentication));         
            }
        }
        // continue thru the filter chain
        chain.doFilter(request, response);
    }
}

분명히 *'TokenUtils'는 일부 개인 정보(그리고 매우 사례별) 코드를 포함하고 있어 쉽게 공유할 수 없습니다. 인터페이스는 다음과 같습니다.

public interface TokenUtils {
    String getToken(UserDetails userDetails);
    String getToken(UserDetails userDetails, Long expiration);
    boolean validate(String token);
    UserDetails getUserFromToken(String token);
}

그럼 출발이 좋겠군요. 행복한 코딩. :)

해설 (32)

[Digest Access Authentication][1]을(를) 고려할 수 있습니다. 기본적으로 프로토콜은 다음과 같습니다.

  1. 클라이언트에서 요청함
  2. 서버가 고유한 nonce 문자열로 응답함
  3. 클라이언트가 nonce와 함께 해시된 사용자 이름 및 암호(및 일부 다른 값) md5를 제공함, 이 해시를 HA1
  4. 라고 함
  5. 그런 다음 서버는 클라이언트 ID를 확인하고 요청된 자료를 제공할 수 있습니다.
  6. 서버가 새로운 난스(재생 공격을 제거하기 위해 카운터를 사용)를 제공할 때까지 난스와의 통신이 계속될 수 있습니다

이 모든 통신은 jmort253이 지적한 바와 같이 일반적으로 URL 매개 변수의 민감한 자료를 통신하는 것보다 더 안전한 헤더를 통해 이루어진다.

다이제스트 액세스 인증은 [Spring Security][2]에서 지원됩니다. 문서에 클라이언트의 일반 텍스트 암호에 대한 액세스 권한이 있어야 한다고 나와 있지만 클라이언트에 대한 HA1 해시[3]가 있으면 [인증 성공]할 수 있습니다.

[1]http://tools.ietf.org/html/rfc2617#section-3 [2]http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#digest-processing-filter [3]https://jira.springsource.org/browse/SEC-1905

해설 (2)

정보를 전달하는 토큰에 대해서는 JSON 웹토큰(http://jwt.io)이 뛰어난 기술이다. 주요 개념은 정보 요소(청구)를 토큰에 내장한 다음 전체 토큰에 서명하여 검증 엔드가 클레임이 실제로 신뢰할 수 있는지 확인할 수 있도록 하는 것이다.

저는 자바 구현을 사용합니다: https://bitbucket.org/b_c/jose4j/wiki/Home

스프링 모듈(spring-security-jwt)도 있지만 어떤 모듈을 지원하는지 알아본 적이 없다.

해설 (0)

39 로 OAuth 를 사용하기 때문에, JSON 웹토컨스 don& t you

http://projects.spring.io/spring-security-oauth/

OAuth2 백업이었습니다 표준화했습니다 인증 프로토콜 / 레임워크. 이에 따라 OAuth2 사양명세:

Here 더욱 다양한 정보를 얻으실 수 있습니다

해설 (0)