Spring Security - Oauth2将请求参数传递给AuthenticationProvider

时间:2016-11-04 09:09:40

标签: java spring-security

我创建了一个自定义身份验证提供程序,我需要从请求中传递参数。

要点是

  

/的OAuth /令牌grant_type =密码&安培;用户名= XXX&安培;密码= XXX&安培; CLIENT_ID = XXX&安培; client_secret = XXX&安培;国家=我

根据上述请求,我需要捕获country参数并将其传递给自定义身份验证提供程序,然后该身份验证提供程序将根据用户名,密码和国家/地区对用户进行身份验证。

上述请求通过ClientCredentialsTokenEndpointFilter过滤器,但我无法将请求中的国家/地区值设置为身份验证对象。

<http pattern="/oauth/token" create-session="never"
    authentication-manager-ref="clientAuthenticationManager" 
    xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/token" access="fullyAuthenticated" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />     
    <custom-filter ref="clientCredentialsTokenEndpointFilter"
        after="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

如果我可以通过扩展任何安全功能来实现此功能,请通知我。

我正在使用Spring 4.1Spring Security 4.0.3RELEASE

谢谢, 安华

1 个答案:

答案 0 :(得分:0)

您需要创建UsernamePasswordCountryAuthenticationToken

public class UsernamePasswordCountryAuthenticationToken extends UsernamePasswordAuthenticationToken {

    private String country;

    public UsernamePasswordCountryAuthenticationToken(Object principal, Object credentials, String country, Collection<? extends GrantedAuthority> authorities)    {
        super(principal, credentials, country, authorities);
    }

    public UsernamePasswordCountryAuthenticationToken(Object principal, Object credentials, String country)    {
        super(principal, credentials, country);
    }

    public String getCountry() {
        return country;
    }
}

并覆盖ResourceOwnerPasswordTokenGranter

public class CustomResourceOwnerPasswordTokenGranter extends AbstractTokenGranter {

    private static final String GRANT_TYPE = "password";

    private final AuthenticationManager authenticationManager;

    public CustomResourceOwnerPasswordTokenGranter(AuthenticationManager authenticationManager,
        AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService) {
        super(tokenServices, clientDetailsService, GRANT_TYPE);
        this.authenticationManager = authenticationManager;
    }


    protected OAuth2Authentication getOAuth2Authentication(AuthorizationRequest clientToken) {
        Map<String, String> parameters = clientToken.getAuthorizationParameters();
        String username = parameters.get("username");
        String password = parameters.get("password");
        String country = parameters.get("country");

        Authentication userAuth = new UsernamePasswordCountryAuthenticationToken(username, password, country);
        try {
             userAuth = authenticationManager.authenticate(userAuth);
        } catch (AccountStatusException ase) {
            //covers expired, locked, disabled cases (mentioned in section 5.2, draft 31)
            throw new InvalidGrantException(ase.getMessage());
        } catch (BadCredentialsException e) {
            // If the username/password are wrong the spec says we should send 400/bad grant
            throw new InvalidGrantException(e.getMessage());
        }

        if (userAuth == null || !userAuth.isAuthenticated()) {
            throw new InvalidGrantException("Could not authenticate user: " + username);
        }

        return new OAuth2Authentication(clientToken, userAuth);
    }
}

最后在Spring Security OAuth配置文件中

<bean id="customResourceOwnerPasswordTokenGranter" class="CustomResourceOwnerPasswordTokenGranter">
    <constructor-arg index="0" ref="authenticationManager"/>
    <constructor-arg index="1" ref="tokenServices"/>
    <constructor-arg index="2" ref="clientDetailsService"/>
</bean>

<oauth:authorization-server ...>
    <oauth:custom-grant token-granter-ref="customResourceOwnerPasswordTokenGranter" />
</oauth:authorization-server>

现在,如果您已正确配置AuthenticationManager以获得自定义AuthenticationProvider,那么您将收到UsernamePasswordCountryAuthenticationTokenAuthenticationProvider.authenticate method(Authentication auth)的实例,您可以在其中{{1}转到auth并使用。