Spring Security Oauth2:处理过期 AccessToken 的流程
Posted
技术标签:
【中文标题】Spring Security Oauth2:处理过期 AccessToken 的流程【英文标题】:Spring Security Oauth2: Flow to Handling Expired AccessToken 【发布时间】:2015-02-08 04:11:43 【问题描述】:我只是 Spring Security Oauth2 的初学者。 我尝试制作授权服务器和资源服务器(分离并连接到 JDBC),目的是进行单点登录。 我从授权服务器获取访问令牌和刷新令牌的流程成功。我的 accesstoken 总是作为参数访问 Resouce Server,这是回馈。
for example http://127.0.0.1:8080/Resource/res/staff?access_token=xxxxxxxxxxxxxxxxxxxxx
我的问题,如果accesstoken过期了,spring security会阻止访问页面并给出错误异常。什么时候必须使用 refreshtoken 来获取新令牌? 还是我的流程错了?是否有其他流程可以更新 accesstoken?
谢谢
已编辑:
仅供参考: 我想使用 Spring Security Oauth2 进行 SSO。我有几个 Apps Server(使用 Spring Framework),我想制作一个负责管理登录的服务器。我想让应用服务器成为资源服务器(也是客户端) 所以我用 Spring Security Oauth2 做了一个授权服务器。想要访问受保护资源服务器的用户必须登录到授权服务器(资源服务器授权给授权服务器)。它将获得一个代码,然后资源服务器将与 accessToken 和 refreshToken 交换此代码。这个流程是成功的。
我还可以使用授权服务器提供的 refreshToken 请求新的 accessToken。 但是我不能调用这个过程,因为如果我访问 url 映射,以前 spring security 会阻止访问并返回无效令牌错误。
如何解决丢失的链接?
更新:
这是我的授权服务器配置:
@Configuration
public class Oauth2AuthorizationServer
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
AuthorizationServerConfigurerAdapter
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
DataSource dataSource;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception
endpoints
.tokenStore(new JdbcTokenStore(dataSource))
.authenticationManager(authenticationManager);
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
oauthServer.tokenKeyAccess("isAnonymous() || permitAll()").checkTokenAccess("permitAll()");
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients
.jdbc(dataSource);
这是我的资源服务器配置(也作为客户端)
@Configuration
public class Oauth2ResourceServer
private static final String RESOURCE_ID = "test";
@Configuration @Order(10)
protected static class NonOauthResources extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests()
.antMatchers("/api/halo").permitAll()
.antMatchers("/api/state/**").permitAll()
.antMatchers("/**").permitAll()
.and().anonymous();
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends
ResourceServerConfigurerAdapter
@Override
public void configure(ResourceServerSecurityConfigurer resources)
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setClientId("jsclient");
tokenService.setClientSecret("jspasswd");
tokenService.setCheckTokenEndpointUrl("http://localhost:8084/Server2Auth/oauth/check_token");
resources
.resourceId(RESOURCE_ID)
.tokenServices(tokenService);
@Override
public void configure(HttpSecurity http) throws Exception
http.authorizeRequests()
.filterSecurityInterceptorOncePerRequest(true)
.antMatchers("/res/staff").hasRole("STAFF")
.antMatchers("/res/client").access("#oauth2.hasScope('trust')")
.antMatchers("/res/admin").hasRole("ADMIN")
.and()
.exceptionHandling().accessDeniedPage("/403");
资源(也作为客户端)请求授权:
curl -X POST -vu clientauthcode:123456 http://localhost:10000/auth-server/oauth/token -d "client_id=clientauthcode&grant_type=refresh_token&refresh_token=436761f1-2f26-412b-ab0f-bbf2cd7459c4"
来自授权服务器的反馈:
http://localhost:10001/resource-server/api/state/new?code=8OppiR
资源(作为客户端)将代码交换给授权服务器:
curl -X POST -vu clientauthcode:123456 http://localhost:10000/auth-server/oauth/token -H "Accept: application/json" -d "grant_type=authorization_code&code=iMAtdP&redirect_uri=http://localhost:10001/resource-server/api/state/new"
来自授权服务器的反馈:
"access_token":"08664d93-41e3-473c-b5d2-f2b30afe7053",
"token_type":"bearer",
"refresh_token":"436761f1-2f26-412b-ab0f-bbf2cd7459c4",
"expires_in":43199,
"scope":"write read"
资源(作为客户端)访问 url 本身
curl http://localhost:10001/resource-server/api/admin?access_token=08664d93-41e3-473c-b5d2-f2b30afe7053
使用刷新令牌请求新的访问令牌
curl -X POST -vu clientauthcode:123456 http://localhost:10000/auth-server/oauth/token -d "client_id=clientauthcode&grant_type=refresh_token&refresh_token=436761f1-2f26-412b-ab0f-bbf2cd7459c4"
【问题讨论】:
无关注释:您应该将访问令牌放在标头中(作为 URI 查询参数不安全)。 另一个无关的评论:你不需要令牌密钥端点,所以不要触摸它;并且检查令牌端点不应在生产服务器中使用permitAll()
公开(尝试isAuthenticated()
)。
有点相关的评论(因为它使问题产生误导)你在这里没有做任何 SSO。它是经典的身份验证/资源服务器,在资源服务器中具有基于令牌的安全性。
我认为授权码的curl命令错误(复制粘贴错误)?
可能是clientID、clientSecret或者code不同。我可以使用 curl(更改 clientID、clientSecret 和代码)
【参考方案1】:
The OAuth2 Spec 有一个关于刷新访问令牌的部分。它在 Spring OAuth 中以非常标准的方式实现(您只需将刷新令牌发布到 /token 端点)。
顺便说一句,对于 SSO,您通常不需要资源服务器。但这是一个不同的问题。
【讨论】:
没问题。乐意效劳。如果我的回答有帮助,请接受,这样其他人就会知道它可能对他们有帮助。 对不起,我也是 Oauth2 的初学者。在 Ouath2 规范中说“授权服务器可以发出新的刷新令牌”,Spring Security Oauth2 如何给出问题?我可以通过refreshtoken请求获取新的accesstoken,但是我只知道accesstoken在访问某些资源时过期了。仅供参考,我的 SSO 将授权和资源服务器分开,因为在此之前我有多个资源服务器,所以我认为我可以将授权服务器与我的资源分开。 如果您启用它们,Spring Auth Server 会发出刷新令牌(它可能不是默认设置,我忘记了)。当颁发访问令牌时,客户端大约知道它何时到期,因此它可以使用该信息或等待 401。 我只是启用了刷新令牌。我想等待 401,然后我可以调用该过程以使用刷新令牌请求新的访问令牌。但是不知道怎么做401处理程序? 如果你使用OAuth2RestTemplate
,它应该是自动的。否则我想看看源代码并复制模式。以上是关于Spring Security Oauth2:处理过期 AccessToken 的流程的主要内容,如果未能解决你的问题,请参考以下文章
spring security oauth2 认证端异常处理(基于前后分离统一返回json)
Spring Security 实战内容:OAuth2授权回调的处理机制
Spring Security Oauth2:处理过期 AccessToken 的流程
Spring Security OAuth2 授权服务器 /oauth/token - 500 处理程序没有适配器