【笔记】Spring Security Oauth2

模式

身份认证系统oauth2的四种模式

  1. 授权码模式 【第三方Web服务器端应用与第三方原生App】【采用】
  2. 简化模式 【第三方单页面应用】
  3. 密码模式 【第一方单页应用与第一方原生App】【采用】
  4. 客户端模式 【没有用户参与的,完全信任的服务器端服务】

需求

项目系统需要类似微信类似开发平台,让第三方能够接入进来正常的访问

使用

Oauth2回调地址设置。配置能够让授权码模式的运用主动权掌握到自己手里,根据第三方不同项目实际情况设置不同的回调

源码

DefaultRedirectResolver

org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver源码:

	/**
	 * Grant types that are permitted to have a redirect uri.
	 * 重定向解析程序的默认实现
	 * @param redirectGrantTypes the redirect grant types to set
	 */
	public void setRedirectGrantTypes(Collection<String> redirectGrantTypes) {
		this.redirectGrantTypes = new HashSet<String>(redirectGrantTypes);
	}

	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.");
		}
		if (!containsRedirectGrantType(authorizedGrantTypes)) {
			throw new InvalidGrantException(
					"A redirect_uri can only be used by implicit or authorization_code grant types.");
		}

		Set<String> registeredRedirectUris = client.getRegisteredRedirectUri();
		if (registeredRedirectUris == null || registeredRedirectUris.isEmpty()) {
			throw new InvalidRequestException("At least one redirect_uri must be registered with the client.");
		}
		return obtainMatchingRedirect(registeredRedirectUris, requestedRedirect);
	}

对重定向路径进行解析,如果不进行设置默认就是当前路径,譬如:当你访问security进行犿控制的路径http://example.com,跳转到oauth2的登录首页,点前页面指的就是http://example.com。方法来判断客户端的设置回调地址和服务端的回调地址是否一致,如下:

	/**
	 * Attempt to match one of the registered URIs to the that of the requested one.
	 * 尝试将其中一个已注册的URI与所请求的URI进行匹配。
	 * @param redirectUris the set of the registered URIs to try and find a match. This cannot be null or empty.
	 * @param requestedRedirect the URI used as part of the request
	 * @return the matching URI
	 * @throws RedirectMismatchException if no match was found
	 */
	private String obtainMatchingRedirect(Set<String> redirectUris, String requestedRedirect) {
		Assert.notEmpty(redirectUris, "Redirect URIs cannot be empty");

		if (redirectUris.size() == 1 && requestedRedirect == null) {
			return redirectUris.iterator().next();
		}
		for (String redirectUri : redirectUris) {
			if (requestedRedirect != null && redirectMatches(requestedRedirect, redirectUri)) {
				return requestedRedirect;
			}
		}
		throw new RedirectMismatchException("Invalid redirect: " + requestedRedirect
				+ " does not match one of the registered values.");
	}

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;
import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;

/**
 * @author Dave Syer
 */
public abstract class AbstractRedirectResourceDetails extends BaseOAuth2ProtectedResourceDetails {

	private String preEstablishedRedirectUri;

	private String userAuthorizationUri;

	private boolean useCurrentUri = true;

	/**
	 * Flag to signal that the current URI (if set) in the request should be used in preference to the pre-established
	 * redirect URI.
	 * 
	 * @param useCurrentUri the flag value to set (default true)
	 */
	public void setUseCurrentUri(boolean useCurrentUri) {
		this.useCurrentUri = useCurrentUri;
	}
	
	/**
	 * Flag to signal that the current URI (if set) in the request should be used in preference to the pre-established
	 * redirect URI.
	 * 
	 * @return the flag value
	 */
	public boolean isUseCurrentUri() {
		return useCurrentUri;
	}

	/**
	 * The URI to which the user is to be redirected to authorize an access token.
	 * 
	 * @return The URI to which the user is to be redirected to authorize an access token.
	 */
	public String getUserAuthorizationUri() {
		return userAuthorizationUri;
	}

	/**
	 * The URI to which the user is to be redirected to authorize an access token.
	 * 
	 * @param userAuthorizationUri The URI to which the user is to be redirected to authorize an access token.
	 */
	public void setUserAuthorizationUri(String userAuthorizationUri) {
		this.userAuthorizationUri = userAuthorizationUri;
	}

	/**
	 * The redirect URI that has been pre-established with the server. If present, the redirect URI will be omitted from
	 * the user authorization request because the server doesn't need to know it.
	 * 
	 * @return The redirect URI that has been pre-established with the server.
	 */
	public String getPreEstablishedRedirectUri() {
		return preEstablishedRedirectUri;
	}

	/**
	 * The redirect URI that has been pre-established with the server. If present, the redirect URI will be omitted from
	 * the user authorization request because the server doesn't need to know it.
	 * 
	 * @param preEstablishedRedirectUri The redirect URI that has been pre-established with the server.
	 */
	public void setPreEstablishedRedirectUri(String preEstablishedRedirectUri) {
		this.preEstablishedRedirectUri = preEstablishedRedirectUri;
	}

	/**
	 * Extract a redirect uri from the resource and/or the current request.
	 * 
	 * @param request the current {@link DefaultAccessTokenRequest}
	 * @return a redirect uri if one can be established
	 */
	public String getRedirectUri(AccessTokenRequest request) {

		String redirectUri = request.getFirst("redirect_uri");

		if (redirectUri == null && request.getCurrentUri() != null && useCurrentUri) {
			redirectUri = request.getCurrentUri();
		}

		if (redirectUri == null && getPreEstablishedRedirectUri() != null) {
			// Override the redirect_uri if it is pre-registered
			redirectUri = getPreEstablishedRedirectUri();
		}

		return redirectUri;

	}

}

Get请求

http://localhost:3000/oauth/authorize?response_type=code&client_id=test&redirect_uri=http://example.com&scope=all

输入账号密码后,成功跳转到http://example.com
【笔记】Spring Security Oauth2

参考:
OAuth 2.0
https://oauth.net/2/

Spring Security Oauth2系列(七)
https://blog.csdn.net/sinat_24798023/article/details/80537179

OAuth2.0协议入门(一):OAuth2.0协议的基本概念以及使用授权码模式(authorization code)实现百度账号登录
https://www.zifangsky.cn/1309.html