参考:https://blog.csdn.net/weixin_42271016/article/details/104212326
参考:https://segmentfault.com/a/1190000019894976?utm_source=tag-newest
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import java.util.Map;
public abstract class AbstractCustomTokenGranter extends AbstractTokenGranter {
private final OAuth2RequestFactory requestFactory;
protected AbstractCustomTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
super(tokenServices, clientDetailsService, requestFactory, grantType);
this.requestFactory = requestFactory;
}
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
Map<String, String> parameters = tokenRequest.getRequestParameters();
UserDetails userDetails = getUserDetails(parameters);
if (userDetails == null) {
throw new InvalidGrantException("Unable to get user information");
}
OAuth2Request storedOAuth2Request = this.requestFactory.createOAuth2Request(client, tokenRequest);
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(userDetails);
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, authentication);
return oAuth2Authentication;
}
protected abstract UserDetails getUserDetails(Map<String, String> parameters);
import com.freedom.security.auth.config.custom.CustomUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import java.util.Map;
public class PhoneSmsCustomTokenGranter extends AbstractCustomTokenGranter {
private static final String GRANT_TYPE = "phone_sms";
private CustomUserDetailsService userDetailsService;
public PhoneSmsCustomTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, UserDetailsService userDetailsService) {
super(tokenServices, clientDetailsService, requestFactory,GRANT_TYPE);
this.userDetailsService = (CustomUserDetailsService)userDetailsService;
}
@Override
protected UserDetails getUserDetails(Map<String, String> parameters) {
String phone = parameters.get("phone");
String smsCode = parameters.get("sms_code");
return userDetailsService.loadUserByPhoneAndSmsCode(phone, smsCode);
}
}
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
public interface CustomUserDetailsService extends UserDetailsService {
/**
* 通过手机号和短信获取用户信息
* @param phone
* @param smsCode
* @return
*/
UserDetails loadUserByPhoneAndSmsCode(String phone, String smsCode);
}
@Component
public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
@Autowired
private IUserService iUserService;
@Autowired
private IUserRoleService userRoleService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 编辑验证账号密码逻辑并返回UserDetails信息
return null;
}
@Override
public UserDetails loadUserByPhoneAndSmsCode(String phone, String captcha) {
// 编辑短信验证逻辑并返回UserDetails信息
return null;
}
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
List<TokenGranter> tokenGranters = getTokenGranters(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory());
// 添加自定义令牌授权策略
List<TokenGranter> tokenGranters = getDefaultTokenGranters(
endpoints.getTokenServices(),
endpoints.getClientDetailsService(),
endpoints.getAuthorizationCodeServices(),
endpoints.getOAuth2RequestFactory(),
this.authenticationManager,
userDetailsService);
endpoints
.authenticationManager(this.authenticationManager)
// 指定令牌授权者
.tokenGranter(new CompositeTokenGranter(tokenGranters))
}
/**
* 获取令牌授权策略
* @param tokenServices
* @param clientDetailsService
* @param authorizationCodeServices
* @param requestFactory
* @param authenticationManager
* @param userDetailsService
* @return
*/
private List<TokenGranter> getDefaultTokenGranters(AuthorizationServerTokenServices tokenServices,
ClientDetailsService clientDetailsService,
AuthorizationCodeServices authorizationCodeServices,
OAuth2RequestFactory requestFactory,
AuthenticationManager authenticationManager,
UserDetailsService userDetailsService) {
List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetailsService,
requestFactory));
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory));
ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory);
tokenGranters.add(implicit);
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory));
if (authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices,
clientDetailsService, requestFactory));
}
// 添加自定义短信令牌授权者
tokenGranters.add(new PhoneSmsCustomTokenGranter(tokenServices, clientDetailsService, requestFactory, userDetailsService));
return tokenGranters;
}
主要是这里追加自定义的令牌策略,其他策略维持源码不变
// 添加自定义短信令牌授权者
tokenGranters.add(new PhoneSmsCustomTokenGranter(tokenServices, clientDetailsService, requestFactory, userDetailsService));
return tokenGranters;
经过以上调整添加了新的grant类型为 "phone_sms"
,并且新增入参"phone"
、 "sms_code"
两个参数