복붙노트

[SPRING] spring-oauth2 로그인 성공 처리기

SPRING

spring-oauth2 로그인 성공 처리기

spring-oauth2를 사용하여 로그인 성공 처리기를 추가하는 방법이 있습니까?

기본 인증 필터를 사용하여 시도했지만 사용자 자격 증명이 아닌 클라이언트 자격 증명 만 필터링합니다.

또는 사용자 정의 사용자 인증 관리자를 만들어야합니까?

티아

해결법

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

    1.이 솔루션은 암호 흐름 및 다른 사람들을 위해 잘 모르겠습니다. oauth-server config에있는 http 태그의 "before = BASIC_AUTH_FILTER"위치에 사용자 정의 필터를 추가 할 수 있습니다. "oauth / token"응답을 구문 분석하여 달성 할 수 있으므로 응답을 얻으려면 ByteArrayResponseWrapper를 작성하고,  여기서는 "org.apache.commons commons-io"의 TeeOutputStream 클래스를 사용하고 있습니다.

    이 솔루션은 암호 흐름 및 다른 사람들을 위해 잘 모르겠습니다. oauth-server config에있는 http 태그의 "before = BASIC_AUTH_FILTER"위치에 사용자 정의 필터를 추가 할 수 있습니다. "oauth / token"응답을 구문 분석하여 달성 할 수 있으므로 응답을 얻으려면 ByteArrayResponseWrapper를 작성하고,  여기서는 "org.apache.commons commons-io"의 TeeOutputStream 클래스를 사용하고 있습니다.

    private class ByteArrayResponseWrapper extends HttpServletResponseWrapper {
    
        public ByteArrayResponseWrapper(ServletResponse response) {
            super((HttpServletResponse) response);
        }
    
        private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return new DelegatingServletOutputStream(new TeeOutputStream(
                    super.getOutputStream(), byteArrayOutputStream));
        }
    
        public byte[] getByteArray() {
            return this.byteArrayOutputStream.toByteArray();
        }
    }
    

    나는 토큰 추출기를 생성하여 access_token을 추출하는 코드를 분리했다.

    public class OAuth2AccessTokenExtractor implements
        OAuth2AccessTokenExtractor {
    
    private ObjectMapper mapper = new ObjectMapper();
    
    public String getAccessTokenValue(byte[] response) {
        try {
            return mapper.readValue(response, OAuth2AccessToken.class)
                    .getValue();
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
     }
    
    }
    

    필터를 만든 후 doFilter를 다음과 같이 재정의하십시오.

    private DefaultTokenServices tokenServices;
    
    private OAuth2AccessTokenExtractor tokenExtractor;
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
    
        // create wrapper to read response body
        ByteArrayResponseWrapper responseWraper = new ByteArrayResponseWrapper(
                response);
    
        // led them go
        chain.doFilter(request, responseWraper);
    
        // get ClientAuthentication
        Authentication clientAuthentication = SecurityContextHolder
                .getContext().getAuthentication();
    
        // is authenticated or not to proceed
        if (clientAuthentication != null
                && clientAuthentication.isAuthenticated()) {
    
            // callBack client authenticated successfully
            onSuccessfulClientAuthentication(request, response,
                    clientAuthentication);
    
            // check response status is success of failure
            if (responseWraper.getStatus() == 200) {
    
                // extract accessToken from response
                String token = tokenExtractor
                        .getAccessTokenValue(responseWraper.getByteArray());
    
                if (token != null && !token.isEmpty()) {
    
                    // load authentication from token
                    OAuth2Authentication oAuth2Authentication = this.tokenServices
                            .loadAuthentication(token);
                    OAuth2AccessToken actualAccessToken = this.tokenServices
                            .getAccessToken(oAuth2Authentication);
    
                    // callBack user authenticated successfully
                    onSuccessfulUserAuthentication(request, response,
                            clientAuthentication, oAuth2Authentication,
                            actualAccessToken);
                } else {
                    log.error("access token is empty from extractor");
                }
            } else {
                // callBack user authenticated failure
                onFailureUserAuthentication(request, response,
                        clientAuthentication, request.getParameter("username"));
            }
        } else {
            // callBack client authenticated failure
            onFailClientAuthentication(request, response,
                    request.getParameter(OAuth2Utils.CLIENT_ID));
        }
    }
    
    protected void onSuccessfulClientAuthentication(ServletRequest request,
            ServletResponse response, Authentication authentication) {
    }
    
    protected void onFailClientAuthentication(ServletRequest request,
            ServletResponse response, String clientId) {
    }
    
    protected void onSuccessfulUserAuthentication(ServletRequest request,
            ServletResponse response, Authentication clientAuthentication,
            OAuth2Authentication userOAuth2Authentication,
            OAuth2AccessToken token) {
    }
    
    protected void onFailureUserAuthentication(ServletRequest request,
            ServletResponse response, Authentication clientAuthentication,
            String username) {
    }
    

    필터 인스턴스 인젝션 tokenServices를 생성합니다. OnSuccessfulClientAuthentication, onFailClientAuthentication, onSuccessfulUserAuthentication 및 onFailureUserAuthentication이 인증에 따라 호출됩니다.

    더 많은 정보는 github에서이 코드를 참조하십시오.

    편집 됨 :

    위의 스 니펫은 기본 토큰 응답이 있고 ServletResponseWrapper를 사용하고 추출 할 때 잘 작동합니다. 하지만 여전히 취약한 것처럼 보이므로 org.springframework.security.oauth2.provider.token.TokenEnhancer 클래스를 통해 사용자 인증 성공을 알 수 있습니다.

    자세한 내용은이 답변을 따르십시오.

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

    2.이 작업을 수행하기 위해 OAuth2AuthenticationProcessingFilter에 연결 한 사용자 정의 인증 관리자를 구축했습니다. 관리자의 authenticate 메소드는 인증 주체에서 OAuth2Authentication 및 OAuth2AuthenticationDetails의 압축을 풀 수 있습니다.

    이 작업을 수행하기 위해 OAuth2AuthenticationProcessingFilter에 연결 한 사용자 정의 인증 관리자를 구축했습니다. 관리자의 authenticate 메소드는 인증 주체에서 OAuth2Authentication 및 OAuth2AuthenticationDetails의 압축을 풀 수 있습니다.

    <bean id="oAuth2AuthenticationManager" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager">
        <property name="resourceId" value="XXX-api"/>
        <property name="tokenServices" ref="tokenServices"/>
    </bean>
    
    <bean id="resourceServerFilter"
          class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter">
        <property name="authenticationManager" ref="oAuth2AuthenticationManager"/>
        <property name="tokenExtractor">
            <bean class="com.xxx.oauth.BearerTokenExtractor"/>
        </property>
    </bean>
    
  3. from https://stackoverflow.com/questions/29339027/spring-oauth2-login-success-handler by cc-by-sa and MIT license