TokenEndpoint类中可以看到入口/oauth/token
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
String clientId = getClientId(principal);
ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);
TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);
if (clientId != null && !clientId.equals("")) {
if (!clientId.equals(tokenRequest.getClientId())) {
throw new InvalidClientException("Given client ID does not match authenticated client");
}
}
if (authenticatedClient != null) {
oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
}
if (!StringUtils.hasText(tokenRequest.getGrantType())) {
throw new InvalidRequestException("Missing grant type");
}
if (tokenRequest.getGrantType().equals("implicit")) {
throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
}
if (isAuthCodeRequest(parameters)) {
if (!tokenRequest.getScope().isEmpty()) {
logger.debug("Clearing scope of incoming token request");
tokenRequest.setScope(Collections.<String> emptySet());
}
}
if (isRefreshTokenRequest(parameters)) {
tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
}
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
if (token == null) {
throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
}
return getResponse(token);
}
打断点找一下源码是在哪里加入四种模式的授权的
OAuth2AccessToken token = this.getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
this.getTokenGranter()会调用this.tokenGranter()
在这个this.getDefaultTokenGranters()里面会添加授权模式进去
private List<TokenGranter> getDefaultTokenGranters() {
ClientDetailsService clientDetails = clientDetailsService();
AuthorizationServerTokenServices tokenServices = tokenServices();
AuthorizationCodeServices authorizationCodeServices = authorizationCodeServices();
OAuth2RequestFactory requestFactory = requestFactory();
List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetails,
requestFactory));
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetails, requestFactory));
ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
tokenGranters.add(implicit);
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory));
if (authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices,
clientDetails, requestFactory));
tokenGranters.add(new SmsTokenGranter(authenticationManager, tokenServices,
clientDetails, requestFactory));
}
return tokenGranters;
}
SmsTokenGranter具体实现
public class SmsTokenGranter extends AbstractTokenGranter {
private static final String GRANT_TYPE = "sms";
private final AuthenticationManager authenticationManager;
public SmsTokenGranter(AuthenticationManager authenticationManager,
AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
}
protected SmsTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices,
ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
super(tokenServices, clientDetailsService, requestFactory, grantType);
this.authenticationManager = authenticationManager;
}
public UserService userService = ApplicationContextAwareUtil.getBean("userServiceImpl");
public RedisUtil redisUtil = ApplicationContextAwareUtil.getBean("redisUtil");
public void checkPhoneSms(Map<String, String> parameters) {
String loginType = (String) parameters.get("loginType");
UserModel userInfo = new UserModel();
if (loginType.equals("email")){
String email = (String) parameters.get("email");
String code = (String) parameters.get("code");
if (StringUtils.isBlank(email)) {
throw new InvalidGrantException("邮箱不能为空!");
}
if (StringUtils.isBlank(code)) {
throw new InvalidGrantException("验证码不能为空!");
}
String codeCache = (String) redisUtil.get(email);
if (StringUtils.isBlank(codeCache)) {
throw new InvalidGrantException("验证码已失效,请重新获取!");
}
if (!code.equals(codeCache)) {
throw new InvalidGrantException("验证码错误!");
}
userInfo = userService.selectUserModelByEmail(email);
}else if (loginType.equals("phone")){
String phone = (String) parameters.get("phone");
String code = (String) parameters.get("code");
if (StringUtils.isBlank(phone)) {
throw new InvalidGrantException("手机号不能为空!");
}
if (StringUtils.isBlank(code)) {
throw new InvalidGrantException("验证码不能为空!");
}
String codeCache = (String) redisUtil.get(phone);
if (StringUtils.isBlank(codeCache)) {
throw new InvalidGrantException("验证码已失效,请重新获取!");
}
if (!code.equals(codeCache)) {
throw new InvalidGrantException("验证码错误!");
}
userInfo = userService.selectUserModelByPhone(phone);
}
parameters.put("username", userInfo.getUserName() + ":");
parameters.put("password", userInfo.getPassword());
}
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
Map<String, String> parameters = new LinkedHashMap<String, String>(tokenRequest.getRequestParameters());
this.checkPhoneSms(parameters);
String username = parameters.get("username");
String password = parameters.get("password");
parameters.remove("password");
Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
((AbstractAuthenticationToken) userAuth).setDetails(parameters);
try {
userAuth = authenticationManager.authenticate(userAuth);
}
catch (AccountStatusException ase) {
throw new InvalidGrantException(ase.getMessage());
}
catch (BadCredentialsException e) {
throw new InvalidGrantException(e.getMessage());
}
if (userAuth == null || !userAuth.isAuthenticated()) {
throw new InvalidGrantException("Could not authenticate user: " + username);
}
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
return new OAuth2Authentication(storedOAuth2Request, userAuth);
}
}
因为在这个类里面无法直接Autowired注入我们需要的类,通过此工具类则可以直接获取spring中的bean
@Component
public class ApplicationContextAwareUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextAwareUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
if (applicationContext == null) {
return null;
}
return (T) applicationContext.getBean(name);
}
}
最后在UserDetailsService的实现类中根据具体业务来写规则,需要注意的是之前用‘:’来区分了自定义的模式和密码模式