Spring Security Oauth2 自定义授权类型实现短信验证码登陆

参考: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);
    }
}

自定义UserDetailsService接口

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);
}

实现CustomUserDetailsService

@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"两个参数
Spring Security Oauth2 自定义授权类型实现短信验证码登陆_第1张图片

你可能感兴趣的:(spring,security,oauth2,spring,java)