cn.bestwu.security.oauth2.social.provider.SocialTokenGranter Maven / Gradle / Ivy
package cn.bestwu.security.oauth2.social.provider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 社交账号登录验证
*
* @author Peter Wu
*/
public class SocialTokenGranter implements TokenGranter {
protected final Log logger = LogFactory.getLog(getClass());
private final AuthorizationServerTokenServices tokenServices;
private final ClientDetailsService clientDetailsService;
private final SocialAdapter socialAdapter;
public SocialTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, SocialAdapter socialAdapter) {
this.clientDetailsService = clientDetailsService;
this.tokenServices = tokenServices;
this.socialAdapter = socialAdapter;
}
@Override
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
grantType = grantType.toLowerCase();
if (!socialAdapter.support(grantType)) {
return null;
}
String clientId = tokenRequest.getClientId();
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
validateGrantType(grantType, client);
logger.debug("Getting access token for: " + clientId);
return tokenServices.createAccessToken(getOAuth2Authentication(grantType, tokenRequest));
}
protected void validateGrantType(String grantType, ClientDetails clientDetails) {
Collection authorizedGrantTypes = clientDetails.getAuthorizedGrantTypes();
if (authorizedGrantTypes != null && !authorizedGrantTypes.isEmpty()
&& !authorizedGrantTypes.contains(grantType)) {
throw new InvalidClientException("Unauthorized grant type: " + grantType);
}
}
protected OAuth2Authentication getOAuth2Authentication(String pid, TokenRequest tokenRequest) {
Map requestParameters = tokenRequest.getRequestParameters();
String puid = requestParameters.get("puid");
String social_token = requestParameters.get("social_token");
if (!StringUtils.hasText(puid)) {
throw new SocialException(HttpStatus.UNPROCESSABLE_ENTITY.value(), "puid must be supplied.");
}
if (!StringUtils.hasText(social_token)) {
throw new SocialException(HttpStatus.UNPROCESSABLE_ENTITY.value(), "social_token must be supplied.");
}
Map originalProfile = socialAdapter.validateSocialTokenAndGetUserOriginalProfile(pid, puid, social_token);
SocialId socialId = socialAdapter.findByPidAndPuid(pid, puid);
if (socialId == null) {
UserProfile userProfile = socialAdapter.originalProfile2UserProfile(pid, puid, originalProfile);
if (socialAdapter.isAutoLogon()) {
try {
socialId = socialAdapter.signup(userProfile);
T user = socialId.getUser();
OAuth2Authentication authentication = socialAdapter.createOAuth2Authentication(user, tokenRequest.getClientId(), tokenRequest.getScope());
//自动登录
SecurityContextHolder.getContext().setAuthentication(authentication);
return authentication;
} catch (ConstraintViolationException e) {
Set> constraintViolations = e.getConstraintViolations();
Map errors = new HashMap<>();
constraintViolations.forEach(constraintViolation -> errors.put(constraintViolation.getPropertyPath().toString(), constraintViolation.getMessage()));
SocialException socialException = new SocialException(HttpStatus.UNPROCESSABLE_ENTITY.value(), errors.values().iterator().next(), userProfile);
socialException.setErrors(errors);
throw socialException;
} catch (DataIntegrityViolationException e) {
String specificCauseMessage = e.getMostSpecificCause().getMessage();
String duplicateRegex = "^Duplicate entry '(.*?)'.*";
String constraintSubfix = "Cannot delete or update a parent row";
String message;
int httpStatusCode = 500;
if (specificCauseMessage.matches(duplicateRegex)) {
httpStatusCode = HttpStatus.UNPROCESSABLE_ENTITY.value();
message = specificCauseMessage.replaceAll(duplicateRegex, "$1") + "已经存在";
if (!StringUtils.hasText(message)) {
message = "数据验证失败";
}
} else if (specificCauseMessage.startsWith(constraintSubfix)) {
httpStatusCode = HttpStatus.UNPROCESSABLE_ENTITY.value();
message = "不能删除或更新关联实体,其他的资源引用了此实体";
if (!StringUtils.hasText(message)) {
message = "数据验证失败";
}
} else {
message = e.getRootCause().getMessage();
logger.error(message, e);
}
throw new SocialException(httpStatusCode, message, userProfile);
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw e;
}
} else {
throw new SocialException(HttpStatus.NOT_FOUND.value(), "账号未初始化", userProfile);
}
} else if (socialAdapter.isRefreshUserProfile()) {
try {
UserProfile userProfile = socialAdapter.originalProfile2UserProfile(pid, puid, originalProfile);
socialAdapter.saveUserProfile(socialId.getUser(), userProfile);
} catch (Exception ignored) {
}
}
return socialAdapter.createOAuth2Authentication(socialId.getUser(), tokenRequest.getClientId(), tokenRequest.getScope());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy