oauth2自定义TokenGranter迁移到springSecurity

前提:auth服务旧版本是用springSecurity oauth2.0实现的,现版本改为springSecurity+jwt
springSecurity原认证流程
在这里插入图片描述

1、SpringSecurity默认自带的拦截器是拦截/login路径,但由于oauth2前用的是oauth/token 接口,考虑到其他产品已接sso登录,为了后续更新兼容旧的sso需要写一个新的拦截器,拦截路径/oauth/token,定义一个EoiAuthenticationFilter
2、在SpringSecurity默认的AuthenticationManager实现类是ProviderManager在ProviderManager中关键代码为通过supports方法去选择到具体的provider
在这里插入图片描述
在这里插入图片描述

为了兼容之前oauth自定义的那些认证方法(根据前端的grantType决定用哪种认证),要需要重写supports校验规则,自定义一个EoiAuthenticationProvider接口(主要是为了重写supports方法传参为String类型)
3、因为重写了supports校验规则,Security默认的ProviderManager就用不了了(接口类型不一致,更主要是为了重写选择规则),需要自定义一个EoiProviderManager继承AuthenticationManager

伪代码:

class EoiAuthenticationFilter extends AbstractAuthenticationProcessingFilter{
    private static final AntPathRequestMatcher OAUTH_TOKEN_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/oauth/token",
            "POST");

    protected EoiAuthenticationFilter(String defaultFilterProcessesUrl) {
        //定义拦截路径
        super(OAUTH_TOKEN_ANT_PATH_REQUEST_MATCHER);
    }
    //重写setDetails方法
    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        //将请求参数传进去
        authRequest.setDetails(request.getParameterMap());
    }
     //其他与UsernamePasswordAuthenticationFilter逻辑一致
      return this.getAuthenticationManager().authenticate(authRequest);
}



//自定义接口
public interface EoiAuthenticationProvider {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
    boolean supports(String grantType);
}

//自定义的认证方式
@Component
public class CaptchaTokenProvider implements EoiAuthenticationProvider {
    public static final String GRANT_TYPE = "captcha";
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //自定义具体逻辑
        return null;
    }
    @Override
    public boolean supports(String grantType) {
        //是否匹配认证方式
        return GRANT_TYPE.equalsIgnoreCase(grantType);
    }
}









//自定义ProviderManager
public class EoiProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Map<String, String[]> details = (Map<String, String[]>) authentication.getDetails();
        for (EoiAuthenticationProvider provider : getProviders()) {
            if(provider.supports(details.get("grant_type")){
                provider.authenticate(authentication)
            }
        }
        //省略其他代码
        //其他与ProviderManage一致
}


//Security配置文件
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
    //由spring注入
    private final List<EoiAuthenticationProvider> providers;
    @Bean
    public PasswordEncoder passwordEncoder() {
        return OriginPasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //设置自定义的密码检验逻辑
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

    @Override
    protected void configure(HttpSecurity http) {
        http.headers().frameOptions().disable();
        //添加拦截器 将自定义的Provider注入到自定义的Manager中
        http.addFilterBefore(new EoiAuthenticationFilter(new EoiProviderManager(providers)), UsernamePasswordAuthenticationFilter.class);
         //添加自定义成功处理器,封装token信息与颁发token
         http.formLogin().successHandler(new EoiAuthenticationSuccessHandler)
           }
}



//springSecurity并没有带RANT_TYPE = "password"; 
@Component
@AllArgsConstructor
public class PasswordProvider extends DaoAuthenticationProvider implements EoiAuthenticationProvider {

    public static final String GRANT_TYPE = "password";

    @Bean
    public PasswordEncoder passwordEncoder() {
        return OriginPasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    private UserDetailsService userDetailsService;

    @PostConstruct
    void init() {
        this.setUserDetailsService(userDetailsService);
        this.setPasswordEncoder(this.passwordEncoder());

    }

    @Override
    public boolean supports(String grantType) {
        return GRANT_TYPE.equalsIgnoreCase(grantType);
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值