All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.bestwu.security.oauth2.social.provider.SignupEndpoint Maven / Gradle / Ivy

package cn.bestwu.security.oauth2.social.provider;

import cn.bestwu.security.oauth2.ClientAuthorize;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpoint;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.util.Assert;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import java.security.Principal;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 用户人工注册
 *
 * @author Peter Wu
 */
@FrameworkEndpoint
public class SignupEndpoint {

	protected final Log logger = LogFactory.getLog(getClass());

	private final WebResponseExceptionTranslator providerExceptionHandler;

	private final SocialAdapter socialAdapter;
	private final AuthorizationServerTokenServices tokenServices;

	/**
	 * 非扩展字段
	 */
	private static final Set EXCLUDE_PARAMS_KEY;

	static {
		EXCLUDE_PARAMS_KEY = new HashSet<>();
		EXCLUDE_PARAMS_KEY.add("pid");
		EXCLUDE_PARAMS_KEY.add("puid");
		EXCLUDE_PARAMS_KEY.add("nickname");
		EXCLUDE_PARAMS_KEY.add("sex");
		EXCLUDE_PARAMS_KEY.add("imageHref");
		EXCLUDE_PARAMS_KEY.add("social_token");
		EXCLUDE_PARAMS_KEY.add("scope");
		EXCLUDE_PARAMS_KEY.add("file");
	}

	public SignupEndpoint(SocialAdapter socialAdapter, AuthorizationServerTokenServices tokenServices, WebResponseExceptionTranslator providerExceptionHandler) {
		this.socialAdapter = socialAdapter;
		this.tokenServices = tokenServices;
		this.providerExceptionHandler = providerExceptionHandler;
	}

	/**
	 * 社交账号注册
	 *
	 * @param principal    principal 客户端信息
	 * @param userProfile  用户资料
	 * @param social_token 社交账号用户资料访问权限授权码
	 * @param scope        权限,访问区域
	 * @param params       参数
	 * @return 结果
	 */
	@ClientAuthorize
	@RequestMapping(value = "/social/account", method = RequestMethod.POST)
	public ResponseEntity signup(Principal principal, UserProfile userProfile, String social_token, String scope,
			@RequestParam Map params) {

		String pid = userProfile.getPid();
		Assert.hasText(pid, "pid must be supplied.");
		String puid = userProfile.getPuid();
		Assert.hasText(puid, "puid must be supplied.");
		Assert.hasText(social_token, "social_token must be supplied.");

		if (!(principal instanceof Authentication)) {
			throw new InsufficientAuthenticationException(
					"There is no client authentication. Try adding an appropriate authentication filter.");
		}

		userProfile.setExtra(parseExtra(params));

		String clientId = getClientId(principal);
		Set scopes = OAuth2Utils.parseParameterList(scope);

		socialAdapter.validateSocialTokenAndGetUserOriginalProfile(pid, puid, social_token);
		SocialId socialId = socialAdapter.findByPidAndPuid(pid, puid);
		if (socialId != null) {
			throw new IllegalArgumentException("social puid registered.");
		}

		socialId = socialAdapter.signup(userProfile);

		T user = socialId.getUser();
		OAuth2Authentication oAuth2Authentication = socialAdapter.createOAuth2Authentication(user, clientId, scopes);

		return getResponse(tokenServices.createAccessToken(oAuth2Authentication));
	}

	/**
	 * 解析扩展参数
	 *
	 * @param params 请求参数
	 * @return 处理后的参数
	 */
	private Map parseExtra(Map params) {
		EXCLUDE_PARAMS_KEY.forEach(params::remove);
		return params;
	}

	/**
	 * @param accessToken accessToken
	 * @return 响应结果
	 */
	private ResponseEntity getResponse(OAuth2AccessToken accessToken) {
		HttpHeaders headers = new HttpHeaders();
		headers.set("Cache-Control", "no-store");
		headers.set("Pragma", "no-cache");
		return new ResponseEntity<>(accessToken, headers, HttpStatus.OK);
	}

	/**
	 * @param principal principal
	 * @return ClientId
	 */
	protected String getClientId(Principal principal) {
		Authentication client = (Authentication) principal;
		if (!client.isAuthenticated()) {
			throw new InsufficientAuthenticationException("The client is not authenticated.");
		}
		String clientId = client.getName();
		if (client instanceof OAuth2Authentication) {
			// Might be a client and user combined authentication
			clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId();
		}
		return clientId;
	}

	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
	public ResponseEntity handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) throws Exception {
		logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
		return getExceptionTranslator().translate(e);
	}

	@ExceptionHandler(Exception.class)
	public ResponseEntity handleException(Exception e) throws Exception {
		logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
		return getExceptionTranslator().translate(e);
	}

	@ExceptionHandler(ClientRegistrationException.class)
	public ResponseEntity handleClientRegistrationException(Exception e) throws Exception {
		logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
		return getExceptionTranslator().translate(new BadClientCredentialsException());
	}

	@ExceptionHandler(OAuth2Exception.class)
	public ResponseEntity handleException(OAuth2Exception e) throws Exception {
		logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
		return getExceptionTranslator().translate(e);
	}

	protected WebResponseExceptionTranslator getExceptionTranslator() {
		return providerExceptionHandler;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy