Oauth2.0 认证服务器添加验证码登陆方式

发送验证码

@RestController
@AllArgsConstructor
@RequestMapping
public class LoginController {

    private final RedisTemplate<String, String> redisTemplate;

    @GetMapping(value = "captcha/{phone}")
    public R captcha(@PathVariable String phone) {
        String captcha = randomCode();
        redisTemplate.opsForValue().set(phone, captcha, 600, TimeUnit.SECONDS);
        return R.ok(captcha);
    }

    private static String randomCode() {
        Random random = new Random();
        int code = random.nextInt(10000);
        DecimalFormat format = new DecimalFormat("0000");
        return format.format(code);
    }

}

登陆验证码校验过滤器 CaptchaFilter

@Slf4j
@Component
@RequiredArgsConstructor
public class CaptchaFilter extends OncePerRequestFilter {

    private final RedisTemplate<String, String> redisTemplate;
    private final UserService userService;
    private RequestMatcher requestMatcher = new AntPathRequestMatcher("/oauth/token", HttpMethod.POST.name());

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (requestMatcher.matches(request)) {
            String grantType = request.getParameter("grant_type");
            if (StrUtil.equalsIgnoreCase(grantType, "captcha")) {
                try {
                    verifyCaptcha(request);
                } catch (BusinessException e) {
                    log.error("登陆验证码校验异常: {}, {}", e.getCode(), e.getMsg());
                    R.failRender(e.getCode(), e.getMsg(), response, HttpStatus.INTERNAL_SERVER_ERROR.value());
                    return;
                }
            }
        }
        filterChain.doFilter(request, response);
    }

    private void verifyCaptcha(HttpServletRequest request) throws ServletRequestBindingException {
        String phone = ServletRequestUtils.getStringParameter(request, "username");
        String captcha = ServletRequestUtils.getStringParameter(request, "password");
        String cache = redisTemplate.opsForValue().get(phone);
        if (Objects.isNull(cache) || !captcha.equals(cache)) {
            throw new BusinessException("验证码校验异常");
        }
    }
}

自定义一种授权模式 CaptchaTokenGranter

  • 自定义验证码授权模式
  • 配置到 AuthorizationServerConfig.tokenGranter()
  • 将配置好的授权列表添加到 AuthorizationServerEndpointsConfigurer 中
public class CaptchaTokenGranter extends AbstractTokenGranter {

    private static final String GRANT_TYPE = "captcha";
    private UserDetailsServiceImpl userDetailsServiceImpl;

    public CaptchaTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, UserDetailsServiceImpl userDetailsServiceImpl) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.userDetailsServiceImpl = userDetailsServiceImpl;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        Map<String, String> requestParameters = tokenRequest.getRequestParameters();
        String username = requestParameters.getOrDefault("username", "");
        UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(username);
        if (Objects.isNull(userDetails)) {
            throw new UsernameNotFoundException("Username Not Found Exception");
        }
        // 构建用户授权信息
        Authentication user = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),
                userDetails.getPassword(), userDetails.getAuthorities());
        return new OAuth2Authentication(tokenRequest.createOAuth2Request(client), user);
    }
}

将定义的授权模式添加到认证服务器核心配置 AuthorizationServerConfig 的端点配置中

AuthorizationServerConfig 其他配置已省略,详细见 Oauth2.0 认证服务器搭建

@Configuration
@EnableAuthorizationServer
@AllArgsConstructor
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
	
    ......
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenGranter(tokenGranter(endpoints)); //配置授权方式
    }

    /**
     * 先获取已有的五种授权列表,然后将自定义的授权方式置入
     *
     * @param endpoints AuthorizationServerEndpointsConfigurer
     * @return TokenGranter
     */
    private TokenGranter tokenGranter(final AuthorizationServerEndpointsConfigurer endpoints) {
        List<TokenGranter> granters = new ArrayList<>(Collections.singletonList(endpoints.getTokenGranter()));
        granters.add(new CaptchaTokenGranter(endpoints.getTokenServices(), endpoints.getClientDetailsService(),
                endpoints.getOAuth2RequestFactory(), userDetailsServiceImpl));
        return new CompositeTokenGranter(granters);
    }
    
    ......

}

Oauth2.0 系列文章

以下是同步到语雀的、可读性好一点,CSDN 继续看的点专栏就好。
Oauth2.0 核心篇
Oauth2.0 安全性(以微信授权登陆为例)
Oauth2.0 认证服务器搭建
Oauth2.0 添加验证码登陆方式
Oauth2.0 资源服务器搭建
Oauth2.0 自定义响应值以及异常处理
Oauth2.0 补充

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值