java me.kimloong.resource.sample.ResourceSampleApplication
此处为显示效果进行了分行
- 实例1
java me.kimloong.resource.sample.ResourceSampleApplication
--server.port=8761
--eureka.instance.hostname=registry1.kimloong.me
--eureka.client.register-with-eureka=true
--eureka.client.fetch-registry=true
--eureka.client.service-url.defaultZone=http://registry2.kimloong.me:8762/eureka/
- 实例2
java me.kimloong.resource.sample.ResourceSampleApplication
--server.port=8762
--eureka.instance.hostname=registry2.kimloong.me
--eureka.client.register-with-eureka=true
--eureka.client.fetch-registry=true
--eureka.client.service-url.defaultZone=http://registry1.kimloong.me:8761/eureka/
- 实例3
java me.kimloong.resource.sample.ResourceSampleApplication
--server.port=8763
--eureka.instance.hostname=registry3.kimloong.me
--eureka.client.register-with-eureka=true
--eureka.client.fetch-registry=true
--eureka.client.service-url.defaultZone=http://registry1.kimloong.me:8761/eureka/
- 启动arangodb
sudo docker run -p 8529:8529 -e ARANGO_ROOT_PASSWORD=root --name user-center-db -d arangodb
- 访问arangodb
http://localhost:8529
- 启动服务
- 使用
maven
执行spring-boot:run
- 注册用户
[POST] http://localhost:8080/uc/users
Header:
无
Body:
{
"username":"user",
"password":"123456"
}
- 在浏览器请求以下链接(以下链接为模拟第三方客户端登录)
http://localhost:5000/oauth/authorize?response_type=code&client_id=microblog-client&redirect_uri=http://localhost:8082/microblog-client
请求会跳转至登录页面,输入用户名密码(步骤4
注册的用户),请求会再次跳转至
http://localhost:8082/microblog-client?code=I5l6xR
复制跳转链接中的code
(即这里的I5l6xR
)
- 获取
token
[POST] http://localhost:8080/uc/oauth/token?grant_type=authorization_code&redirect_uri=http://localhost:8082/microblog-client&code=I5l6xR
Header:
Authorization:Basic bWljcm9ibG9nLWNsaWVudDpzZWNyZXQxMjM=
Body:
无
Header
里的Authorization
为clientId
:clientSecret
进行Base
加密得来的,可以到这里
响应如下:
{
"access_token": "f5970310-ed94-4c0f-8acb-809fe0e626c8",
"token_type": "bearer",
"expires_in": 43199,
"scope": "read"
}
- 向
Resource Server
请求 我们从上一步中得到了access_token
就可以使用它来请求资源服务器,这里以microblog项目为例
[GET] http://localhost:8081/microblog/hello
Header:
Authorization Bearer f5970310-ed94-4c0f-8acb-809fe0e626c8
-
问题描述
Spring Boot
从1.4.x
升级到1.5.x
时,请求的Bearer Token
无法被正确解析 -
问题原因 升级后,
WebSecurityConfig
的config
方法变成在ResourceServerConfig
的config
方法之前执行,导致FilterChainProxy
的filters
顺序发生改变,请求被WebSecurityConfig
注册的Filter
处理了,而处理Bearer Token
的OAuth2AuthenticationProcessingFilter
则是由ResourceServerConfig
注册,未能被正确执行 -
解决方案 在配置文件中指定
security.oauth2.resource.filter-order: 1
-
参考
migrating SpringBoot 1.4.4 to 1.5.1 cause oauth2 NullPointerException on ResourceServer
- 问题描述
Client
控制台报错信息
There was an unexpected error (type=Unauthorized, status=401).
Authentication Failed: Could not obtain access token
.....
Possible CSRF detected - state parameter was present but no state could be found
-
问题原因 通过源码跟踪,发现登录验证成功后在类
AuthorizationCodeAccessTokenProvider
获取preservedState
为空而抛出了异常,猜可能跟cookie
同源机制有关 -
解决方案 将
Authorization Server
与Client
的Context Path
设置成不一样即可,在两者不同host时,则不会有问题。 -
参考
Unable to get EnableOauth2Sso Working — BadCredentialsException: Could not obtain access token
-
问题描述 报
Client
报500 Internal Server Error
,Server
报403 Forbidden
-
问题原因
Server
端的/oauth/check_token
默认为denyAll()
,所以无法进请求成功 -
解决方案
public class OAuth2ProviderConfig extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.checkTokenAccess("fullyAuthenticated");
}
}
- 参考
- 问题描述
在
Resource Server
的ResourceServerConfig
配置了如下权限控制
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.anyRequest().access("#oauth2.hasScope('read')");
}
同时使用UserInfoTokenServices
进行Token
验证
@Bean
public ResourceServerTokenServices tokenService() {
return new UserInfoTokenServices(
resourceServerProperties.getUserInfoUri(),
resourceServerProperties.getClientId());
}
-
问题原因 该报错为
Resource Server
端的报错,实际UAA
已经完成了Token的验证并返回了Principal
,UserInfoTokenServices
仅作为获取用户信息,所以对与Resource Server
端来讲,这是一个认证用户,而无法使用scope
来进行权限验证。如果想验证scope
。 -
解决方案
-
改用
RemoteTokenServices
,配置security.oauth2.resource.token-info-uri
; 因为ResourceServerTokenServicesConfiguration
已有注册一个RemoteTokenServices
因此可以直接省略; 实际user-info-uri
与token-info-uri
都有返回scope
但 -
使用
hasRole('USER')
验证是登录用户
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.anyRequest().access("hasRole('USER')");
}
- 依旧使用
#oauth2.hasScope('read')
,重写UserInfoTokenServices
,查阅参考中的评论
- 参考