摘要:
今天来给大家分享一下期待已久的oauth2回调地址的设置,相信接触过oauth2的很多coder已经按捺不住激动的心情了吧。因为这个回调地址的配置能够让授权码模式的运用的主动权掌握在自己的手中,可以根据自己的不同项目的实际情况设置不同的回调,例如社区的GitHub的示例:Spring Cloud Security系列教程一:入门
DefaultRedirectResolver
首先分析一下org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver源码:
public String resolveRedirect(String requestedRedirect, ClientDetails client) throws OAuth2Exception {
Set<String> authorizedGrantTypes = client.getAuthorizedGrantTypes();
if (authorizedGrantTypes.isEmpty()) {
throw new InvalidGrantException("A client must have at least one authorized grant type.");
} else if (!this.containsRedirectGrantType(authorizedGrantTypes)) {
throw new InvalidGrantException("A redirect_uri can only be used by implicit or authorization_code grant types.");
} else {
Set<String> redirectUris = client.getRegisteredRedirectUri();
if (redirectUris != null && !redirectUris.isEmpty()) {
return this.obtainMatchingRedirect(redirectUris, requestedRedirect);
} else if (StringUtils.hasText(requestedRedirect)) {
return requestedRedirect;
} else {
throw new InvalidRequestException("A redirect_uri must be supplied.");
}
}
}
对重定向路径进行解析,如果不进行设置默认就是当前路径,这里指的当前路径是指:比如当你在访问security进行了权限控制的路径http://localhost:8080/client
时候,跳转到oauth2的登陆首页,此时当前页面指的就是http://localhost:8080/client
private String obtainMatchingRedirect(Set<String> redirectUris, String requestedRedirect) {
Assert.notEmpty(redirectUris, "Redirect URIs cannot be empty");
if (redirectUris.size() == 1 && requestedRedirect == null) {
return (String)redirectUris.iterator().next();
} else {
Iterator var3 = redirectUris.iterator();
String redirectUri;
do {
if (!var3.hasNext()) {
throw new RedirectMismatchException("Invalid redirect: " + requestedRedirect + " does not match one of the registered values: " + redirectUris.toString());
}
redirectUri = (String)var3.next();
} while(requestedRedirect == null || !this.redirectMatches(requestedRedirect, redirectUri));
return requestedRedirect;
}
}
这个方法是来判断客户端的设置回调地址是否和服务端的回调地址一致
AbstractRedirectResourceDetails
核心方法解析,AbstractRedirectResourceDetails
是一个抽象类,位于org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails
一起来看源代码吧
package org.springframework.security.oauth2.client.token.grant.redirect;
import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
public abstract class AbstractRedirectResourceDetails extends BaseOAuth2ProtectedResourceDetails {
private String preEstablishedRedirectUri;
private String userAuthorizationUri;
private boolean useCurrentUri = true;
public AbstractRedirectResourceDetails() {
}
public void setUseCurrentUri(boolean useCurrentUri) {
this.useCurrentUri = useCurrentUri;
}
public boolean isUseCurrentUri() {
return this.useCurrentUri;
}
public String getUserAuthorizationUri() {
return this.userAuthorizationUri;
}
public void setUserAuthorizationUri(String userAuthorizationUri) {
this.userAuthorizationUri = userAuthorizationUri;
}
public String getPreEstablishedRedirectUri() {
return this.preEstablishedRedirectUri;
}
public void setPreEstablishedRedirectUri(String preEstablishedRedirectUri) {
//此处可以在客户端进行自定义设置
this.preEstablishedRedirectUri = preEstablishedRedirectUri;
}
public String getRedirectUri(AccessTokenRequest request) {
String redirectUri = (String)request.getFirst("redirect_uri");
if (redirectUri == null && request.getCurrentUri() != null && this.useCurrentUri) {
redirectUri = request.getCurrentUri();
}
if (redirectUri == null && this.getPreEstablishedRedirectUri() != null) {
redirectUri = this.getPreEstablishedRedirectUri();
}
//返回回调地址
return redirectUri;
}
}
源码特别简单,这里不做过多的解释,部分关键配置我给大家贴出来
我的网关服务配置如下:
security:
oauth2:
client:
client-id: fbed1d1b4b1449daa4bc49397cbe2350
client-secret: fbed1d1b4b1449daa4bc49397cbe2350
access-token-uri: http://localhost:8088/oauth/token
user-authorization-uri: http://localhost:8088/oauth/authorize
scope: read,write
pre-established-redirect-uri: http://localhost:8080/session
use-current-uri: false//此处特别重要一定要配置,否则不会生效,配置了自定义的回调地址就必须将默认的回调禁止,原因不做过多说明。
resource:
user-info-uri: http://localhost:8088/user
prefer-token-info: false
我的oauth2关键配置如下:
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("fbed1d1b4b1449daa4bc49397cbe2350")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read","write")
.secret("fbed1d1b4b1449daa4bc49397cbe2350")
.accessTokenValiditySeconds(120)//Access token is only valid for 2 minutes.
.refreshTokenValiditySeconds(600)//Refresh token is only valid for 10 minutes.
.redirectUris("http://localhost:8080/session");
}
总结:
该篇文章主要讲了oauth2 的回调地址,相信是大家期待已久的功能点了,由于工作上的原因,完成这个分析的主要功能还是我的一个朋友张顺,有问题的大家继续在评论上提出来,希望能够在今后的项目实践中将oauth2的优势体现得淋漓尽致!
参考本人github地址:https://github.com/dqqzj/spring4all/tree/master/oauth2