Java Spring Security OAuth2:通过 POST 接受客户端凭据
我有一个相当基本的 Spring Boot 设置,我已经安装了 Spring Security,并且我已经成功地设置了 OAuth2 来保护我的 API.
I have a fairly basic Spring Boot setup and I have installed Spring Security and I have managed to successfully set up OAuth2 to protect my API.
I had some trouble a few days back and asked (and answered) a question with regards to hitting my /oauth/token
end point. I soon figured out that the problem was that I was trying to send my client credentials in the body of my POST
request but the token end point is configured in Spring Security to accept the client credentials (client_id
and secret
) via HTTP Basic Auth instead.
我使用 OAuth2 API 的大部分经验都涉及在 POST
请求正文中发送客户端凭据,我想知道是否可以将 Spring Security 配置为以相同方式运行?
Most of my experience with consuming OAuth2 APIs has involved sending client credentials in the body of the POST
request and I was wondering if it was possible to configure Spring Security to function in the same way?
我尝试了一些不同的东西但没有成功,比如设置以下配置选项,但我觉得这可能只在配置 OAuth2 客户端时使用:
I've tried a few different things with no success, like setting the following configuration option, but I feel like that might only be used when configuring an OAuth2 client:
security.oauth2.client.clientAuthenticationScheme=form
这是我的授权服务器配置.
This is my Authorization server configuration.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Autowired
private UserApprovalHandler userApprovalHandler;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client_id")
.secret("secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(600)
.refreshTokenValiditySeconds(3600);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(this.tokenStore)
.userApprovalHandler(this.userApprovalHandler)
.authenticationManager(this.authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(this.passwordEncoder);
}
}
正如@chrylis 在评论中指出的,诀窍是使用 allowFormAuthenticationForClients
方法在配置授权服务器时在 AuthorizationServerSecurityConfigurer
上.就我而言,我的 AuthorizationServerConfig
类中有这个:
As pointed out by @chrylis in the comments, the trick is to use the allowFormAuthenticationForClients
method on AuthorizationServerSecurityConfigurer
when configuring the authorization server. In my case, I have this in my AuthorizationServerConfig
class:
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(this.passwordEncoder)
.allowFormAuthenticationForClients();
}
这将允许通过标准参数传递客户端凭据,例如在 POST
请求的正文中(或在查询字符串中),尽管 Spring 更喜欢通过加入 来使用 HTTP 基本身份验证client_id
和 secret
连同冒号 (
),对结果进行 base-64 编码,以 作为前缀Basic
并将其传递给 Authorization
标头,因此您最终会得到如下内容:
That will allow passing client credentials via standard parameters, such as in the body of the POST
request (or in the query string), though Spring prefers using HTTP Basic Auth by joining the client_id
and secret
together with a colon (<client_id>:<secret>
), base-64 encoding the result, prefixing it with Basic
and passing that to the Authorization
header, so you would end up with something like this:
Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l