当前位置: 首页 > 知识库问答 >
问题:

spring-oauth2登录成功处理程序

连俊智
2023-03-14

有没有一种方法可以添加一个登录成功处理程序使用spall-oaut2?

我尝试使用基本身份验证过滤器,但它只过滤客户端凭据,而不是用户凭据。

还是需要创建自定义用户身份验证管理器?

蒂亚

共有2个答案

宋瀚海
2023-03-14

我们构建了一个定制的身份验证管理器,并将其连接到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>
钱振
2023-03-14

这个解决方案将适用于密码流和其他我不确定的问题。您可以在oauth服务器配置中的http标记中的“before=BASIC_AUTH_filter”位置添加自定义过滤器,您可以通过解析“oauth/token”的响应来实现,因此创建ByteArrayResponseWrapper来获得响应,这里我使用的是“org.apache.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();
    }
}

我创建了令牌提取器来分离提取访问令牌的代码

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) {
}

在创建过滤器实例时注入令牌服务。现在将根据您的身份验证调用onSuccessfulClientAuthentication、onFailClientAuthentication、onSuccessfulUserAuthentication和onFailureUserAuthentication

有关更多信息,您可以在github上参考此代码

编辑:

当你有默认的令牌响应时,上面的片段可以正常工作,它只是使用ServletResponse seWrapper和提取。但它仍然看起来很脆弱,所以你可以通过了解用户身份验证成功org.springframework.security.oauth2.provider.token.Token增强器

请按照此答案了解详细信息。

 类似资料:
  • 是否可以为Spring Oauth2 Sso服务设置默认登录成功URL? 紧随塞纳里奥 null 有没有一种方法可以不重定向到上一个受保护的请求的资源,而是默认情况下重定向到'index.html'? 请让我知道,即使没有办法实现这一点

  • 这是application.properties文件的一部分: 一旦登录,用户可以调用这个url/users/{username},但是当他通过OAuth2登录facebook或google时,他会被拒绝,因为权威列表是空的。当他用他的webapp凭据登录时,权威列表包含USER_ROLE,他可以继续操作。 主体对象内部有: null null

  • 我试图在登录symfony2应用程序后实现重定向,以便在我的用户是否有一个属性时重定向。我已在项目的Handler文件夹中创建了AuthenticationSuccessHandler.php类: 但是当我登录时,我得到一个错误: 注意:未定义的属性:Me\MyBundle\Handler\AuthenticationSuccessHandler::$router in/var/www/MyBun

  • 我刚刚在这个论坛的帮助下添加了一个AuthenticationSuccessHandler,当用户通过fosuserbundle或fosfacebookbundle登录时,它在我的站点上实现了重定向。当用户完成或未完成配置文件时,重定向会发生变化,如果已经完成,我希望将它们重定向到以前的位置,这就是我使用referer变量的原因。 security.yml,我已在fos_facebook和form

  • 问题内容: 我的应用程序中有Facebook登录名,并且我正在圈子里奔波,试图让需要通过注册屏幕的新用户和应该直接进入应用程序的注册用户保持平衡。这是处理Facebook登录的功能(当点击按钮并获得Facebook授权时): 在上面的方框中,我基本上说的是,一旦点击Facebook登录按钮并经过Facebook授权,如果用户具有访问令牌,则直接进入应用程序。否则,请转到注册屏幕,用户将在其中输入必

  • 在web.xml中,我有以下内容