oauth2自定义授权认证模式

不废话,直接上代码,具体实现“自定义授权”如下:
1、自定义授权码模式


import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
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 java.util.LinkedHashMap;
import java.util.Map;

/**
 * 自定义授权码模式
 */
public class MyAbstractTokenGranter extends AbstractTokenGranter {

    //我们授权模式注册到oauth中的名称// 这里就是授权模式名
    private static final String GRANT_TYPE = "my_type";

    private AuthenticationManager authenticationManager;

    // 这里创建一个构造函数,配置的时候会用到
    public MyAbstractTokenGranter(AuthenticationManager authenticationManager
            , AuthorizationServerTokenServices tokenServices
            , ClientDetailsService clientDetailsService
            , OAuth2RequestFactory requestFactory) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.authenticationManager = authenticationManager;
    }

    /*
     * 重写方法
     * @param client   客户端详细信息
     * @param tokenRequest  请求参数
     *
     */
    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        // 这里将认证时的请求参数拿到
        Map parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
        //接收传入的参数
        String username = parameters.get("username");authenticationManager.authenticate(userAuth);

        // 这里是我们之前创建的授权前的构造函数,把参数传进去
        Authentication userAuth = new MyAbstractAuthenticationToken(username); // 未认证状态
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);

        // 对参数进行认证
        try {
            userAuth = this.authenticationManager.authenticate(userAuth); // 认证中
        } catch (Exception e) {
            throw new InvalidGrantException(e.getMessage());
        }

        // 判断时候认证成功
        if (userAuth == null || !userAuth.isAuthenticated()) {
            throw new InvalidGrantException("Could not authenticate group company token: " + username);
        }

        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(storedOAuth2Request, userAuth);
    }
}

2、自定义身份授权的Token
 


import java.util.Collection;

/**
 * 自定义身份授权令牌
 */
public class MyAbstractAuthenticationToken extends AbstractAuthenticationToken {
    //我也不知道这个是干嘛用的,反正必须要有
    private final Object principal;

    /** 认证未通过时的初始化方法 */
    public MyAbstractAuthenticationToken(String token){
        super(null);
        this.principal = token;
        setAuthenticated(false);
    }

    /** 认证通过后的初始化方法 */
    public MyAbstractAuthenticationToken(Object principal, Collection authorities){
        super(authorities);
        this.principal = principal;
        super.setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    @Override
    public void setAuthenticated(boolean isAuthenticated) {
        if (isAuthenticated) {
            throw new IllegalArgumentException(
                    "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        }
        super.setAuthenticated(false);
    }
}

3、自定义身份验证

我们可以通过配置类覆盖TokenGranter,在里面注入我们自定义的授权模式!

  • ProviderManager#authenticate(Authentication authentication)这个类是提供了认证的实现逻辑和流程,他负责从所有的AuthenticationProvider中找出具体的Provider进行认证
  • oauth2自定义授权认证模式_第1张图片


/**
 * 自定义身份验证
 */
@Configuration
@RequiredArgsConstructor
public class MyAuthenticationProvider implements AuthenticationProvider {

    private final UserFeignService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) {
        MyAbstractAuthenticationToken myAuthenticationToken = (MyAbstractAuthenticationToken) authentication;
        String userName = (String) myAuthenticationToken.getPrincipal();
        UserDetails user = userDetailsService.loadUserByUsername(userName);        

        MyAbstractAuthenticationToken authenticationToken = new MyAbstractAuthenticationToken(userName, user.getAuthorities());

        authenticationToken.setDetails(myAuthenticationToken.getDetails());
        return authenticationToken;
    }

    @Override
    public boolean supports(Class authentication) {
        return MyAbstractAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

4、认证服务配置中增加自定义的授权

在继承AuthorizationServerConfigurerAdapter的配置类中添加如下代码

    /**
     * @param endpoints
     * @return
     */
    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 获取原有默认授权模式(授权码模式、密码模式、客户端模式、简化模式)的授权者
        List granterList = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter()));
        // 添加自定义授权模式授权者
        granterList.add(new MyAbstractTokenGranter(authenticationManager, endpoints.getTokenServices(),
                endpoints.getClientDetailsService(),
                endpoints.getOAuth2RequestFactory()
                ));
        CompositeTokenGranter compositeTokenGranter = new CompositeTokenGranter(granterList);
 
        //配置存储令牌策略
        endpoints
                //添加自定义模式
                .tokenGranter(tokenGranter(endpoints))
    }

    /**
     * 添加自定义授权类型
     *
     * @return List
     */
    private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) {
        // endpoints.getTokenGranter() 获取SpringSecurity OAuth2.0 现有的授权类型
        List granters = new ArrayList(Collections.singletonList(endpoints.getTokenGranter()));

        // 构建自定义授权类型
        MyTokenGranter smsCodeTokenGranter = new MyTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(),
                endpoints.getOAuth2RequestFactory(), myUserDetailsServiceImpl, authenticationManager);
        // 向集合中添加定义授权类型
        granters.add(smsCodeTokenGranter);
        // 返回所有类型
        return new CompositeTokenGranter(granters);
    }
添加自定义的provider

在SecurityConfig中,初始化provider,代码如下:

@EnableWebSecurity
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;
 
    @Autowired
    private IUserService userService;
 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //实例化provider,把需要的东西set进去
        MyAuthenticationProvider  provider = new MyAuthenticationProvider ();
        provider.setUserDetailsService(userDetailsService);
        auth.authenticationProvider(provider);
    }
}

你可能感兴趣的:(java)