我有一个ios应用程序,它与Grails上开发的REST API进行通信。为了保护REST API,我决定使用oAuth 2.0“资源所有者密码”流程。为了使grails应用程序充当oAuth 2.0提供程序,我使用以下http://grails.org/plugin/spring-security-oauth2-provider 对于身份为“客户”的客户,密码为“1234”,用户名为“用户”,密码为“密码”,请求令牌如下
POST /oauth2-test/oauth/token HTTP/1.1
Host: 192.168.1.113:8080
Authorization: Basic Y2xpZW50OjEyMzQ=
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
grant_type=password&scope=read&username=user&password=password
收到的回复是
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
我对Spring Security和oAuth 2.0提供程序插件的config.groovy编辑看起来像这样
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'test.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'test.UserRole'
grails.plugin.springsecurity.authority.className = 'test.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll'],
'/oauth/authorize.dispatch': ["isFullyAuthenticated() and (request.getMethod().equals('GET') or request.getMethod().equals('POST'))"],
'/oauth/token.dispatch' : ["isFullyAuthenticated() and request.getMethod().equals('POST')"]
]
// Added by the Spring Security OAuth2 Provider plugin:
grails.plugin.springsecurity.oauthProvider.clientLookup.className = 'test.Client'
grails.plugin.springsecurity.oauthProvider.authorizationCodeLookup.className = 'test.AuthorizationCode'
grails.plugin.springsecurity.oauthProvider.accessTokenLookup.className = 'test.AccessToken'
grails.plugin.springsecurity.oauthProvider.refreshTokenLookup.className = 'test.RefreshToken'
grails.plugin.springsecurity.providerNames = [
'clientCredentialsAuthenticationProvider',
'daoAuthenticationProvider',
'anonymousAuthenticationProvider',
'rememberMeAuthenticationProvider'
]
grails.exceptionresolver.params.exclude = ['password', 'client_secret']
grails.plugin.springsecurity.filterChain.chainMap = [
'/oauth/token': 'JOINED_FILTERS,-oauth2ProviderFilter,-securityContextPersistenceFilter,-logoutFilter,-rememberMeAuthenticationFilter',
'/api/**': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-rememberMeAuthenticationFilter',
'/**': 'JOINED_FILTERS,-statelessSecurityContextPersistenceFilter,-oauth2ProviderFilter,-clientCredentialsTokenEndpointFilter'
]
答案 0 :(得分:2)
默认情况下,Spring Security Core中未启用基本身份验证,因此您无法将client_id
和client_secret
置于授权标头中;在这种情况下,只需将它们添加到请求参数(如grant_type
)
以下CURL示例应该有效:
curl -v -X POST \
-d "grant_type=password" \
-d "client_id=client" \
-d "client_secret=1234" \
-d "scope=read" \
-d "username=user" \
-d "password=password" http://localhost:8080/oauth2-test/oauth/token
{"access_token":"d3eb1c1c-9922-4cfc-87e3-7efca9a8a2f2","token_type":"bearer","refresh_token":"e790efc2-e708-4391-9a7b-e4d86dc70816","expires_in":42545,"scope":"read"}
请注意,OAuth2需要HTTPS。如果您使用-https
选项(grails run-app -https
)运行Grails,则命令为:
curl -v --insecure -X POST \
-d "grant_type=password" \
-d "client_id=client" \
-d "client_secret=1234" \
-d "scope=read" \
-d "username=user" \
-d "password=password" https://localhost:8443/oauth2-test/oauth/token
当我省略请求参数client_id
时,我收到以下回复:
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
<强>更新强>
如果您希望能够为client_id使用HTTP基本身份验证,则只需在Spring Security Core中启用基本身份验证(在Config.groovy中)就不是解决方案,因为BasicAuthenticationFilter未以适合oauth2的方式初始化。当凭据正确或省略时,一切都按预期工作,但是当提供凭证但错误时,您将获得HTML响应。
目前项目的Github页面存在一个问题,其中讨论了处理基本身份验证的正确方法:
https://github.com/bluesliverx/grails-spring-security-oauth2-provider/issues/65