spring-oauth2登录成功处理程序 [英] spring-oauth2 login success handler

查看:203
本文介绍了spring-oauth2登录成功处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法使用spring-oauth2添加登录成功处理程序?



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



或者我是否需要创建自定义用户身份验证管理器?



TIA

解决方案

此解决方案适用于密码流,对于其他人我不确定。
您可以在http标签中的before = BASIC_AUTH_FILTER位置添加自定义过滤器,该标签位于oauth-server config,
,您可以通过oauth / token的解析响应来实现,因此创建ByteArrayResponseWrapper得到回复,
这里我使用的是org.apache.commons commons-io中的TeeOutputStream类,

  private class ByteArrayResponseWrapper扩展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

 公共类OAuth2AccessTokenExtractor实现
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();
}
返回null;
}

}

创建过滤器后覆盖doFilter之类这个

  private DefaultTokenServices tokenServices; 

private OAuth2AccessTokenExtractor tokenExtractor;

@Override
public void doFilter(ServletRequest请求,ServletResponse响应,
FilterChain链)抛出IOException,ServletException {

//创建包装器来读取响应体
ByteArrayResponseWrapper responseWraper = new ByteArrayResponseWrapper(
response);

//带领他们去
chain.doFilter(request,responseWraper);

// get ClientAuthentication
身份验证clientAuthentication = SecurityContextHolder
.getContext()。getAuthentication();

//经过身份验证或不进行
if(clientAuthentication!= null
&& clientAuthentication.isAuthenticated()){

/ / callBack客户端成功验证
onSuccessfulClientAuthentication(请求,响应,
clientAuthentication);

//检查响应状态是否成功失败
if(responseWraper.getStatus()== 200){

//从响应中提取accessToken
String token = tokenExtractor
.getAccessTokenValue(responseWraper.getByteArray());

if(token!= null&&!token.isEmpty()){

//从令牌加载身份验证
OAuth2Authentication oAuth2Authentication = this.tokenServices
.loadAuthentication(token);
OAuth2AccessToken actualAccessToken = this.tokenServices
.getAccessToken(oAuth2Authentication);

// callBack用户成功验证
onSuccessfulUserAuthentication(请求,响应,
clientAuthentication,oAuth2Authentication,
actualAccessToken);
} else {
log.error(来自提取器的访问令牌为空);
}
} else {
// callBack用户身份验证失败
onFailureUserAuthentication(请求,响应,
clientAuthentication,request.getParameter(username));
}
} else {
// callBack客户端验证失败
onFailClientAuthentication(请求,响应,
request.getParameter(OAuth2Utils.CLIENT_ID));
}
}

protected void onSuccessfulClientAuthentication(ServletRequest请求,
ServletResponse响应,身份验证身份验证){
}

protected void onFailClientAuthentication(ServletRequest请求,
ServletResponse响应,String clientId){
}

protected void onSuccessfulUserAuthentication(ServletRequest请求,
ServletResponse响应,身份验证clientAuthentication,
OAuth2Authentication userOAuth2Authentication,
OAuth2AccessToken令牌){
}

protected void onFailureUserAuthentication(ServletRequest请求,
ServletResponse响应,身份验证clientAuthentication,
字符串用户名){
}

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



更多您可以在 github



已编辑:



当你有默认的令牌响应并且只是使用ServletResponseWrapper并解压缩时,上面的代码片段工作正常。
但它似乎仍然容易受到攻击,因此你可以通过 org.springframework.security.oauth2.provider.token.TokenEnhancer class <来了解用户身份验证的成功。 / p>

请按照回答了解详情。


Is there a way to add a Login Success Handler using spring-oauth2?

I tried using Basic Authentication Filter but it only filters the client credentials not the user credentials.

Or do I need to create a custom user authentication manager?

TIA

解决方案

This solution will work for password flow and for others I am not sure. You can add your custom filter in position of "before=BASIC_AUTH_FILTER" in http tag which is in oauth-server config, and you can achieve by parse response of "oauth/token" so create ByteArrayResponseWrapper to get response, Here I am using TeeOutputStream class from "org.apache.commons commons-io",

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

and I have created token extractor to separate the code of extracting 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;
 }

}

after create your filter override doFilter like this

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

while create filter instance inject tokenServices. now onSuccessfulClientAuthentication, onFailClientAuthentication, onSuccessfulUserAuthentication and onFailureUserAuthentication will be called according to your authentication

for more you can refer this code on github

Edited:

The above snippet works fine when you have default token response and it is just uses ServletResponseWrapper and extracting. But still it seems like vulnerable so you can get to know the user authentication success by through org.springframework.security.oauth2.provider.token.TokenEnhancer class

Follow this answer for details.

这篇关于spring-oauth2登录成功处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆