如何实现 Oauth2 自定义登录接口以及返回自定义格式?
今天更新文章的原因是粉丝提了个问题:如何实现Oauth2认证服务器自定义登录接口以及返回自定义格式? 这里我给大家分享一个简单且实用的方法,既可以灵活定制登录参数也可以自行组装返回结果。
实现方案
我们知道,认证服务器生成token的入口是TokenEndpoint#postAccessToken(Principal principal, @RequestParam Map parameters),那我们就可以直接在认证服务器自定义一个登录接口,然后组装好TokenEndpoint#postAccessToken()需要的参数,直接调用它生成token后再封装成我们需要的格式即可。
接下来我们直接进入实战:
1. 定义登录参数
/** * 自定义登录参数 * @author JAVA日知录 * @date 2022/5/14 09:23 */@Datapublic class LoginRequest { private String userName; private String password; private String grantType; private String mobile; private String smsCode;}
为了兼容密码模式和自定义的短信验证码模式,我们将所有的参数都放入一个实体,大家可以根据自己的项目需要自行封装。
2. 创建一个登录类型的枚举
public enum LoginTypeEnum { /** * 密码模式 */ PASSWORD(\"password\"), /** * 短信验证码模式 */ SMSCODE(\"sms_code\"); private final String grantType; LoginTypeEnum(String grantType) { this.grantType = grantType; } public String getGrantType() { return grantType; } public static LoginTypeEnum fromGrantType(String grantType){ return www.introzo.com(LoginTypeEnum.values()) .filter(item -> item.getGrantType().equals(grantType)) .findFirst() .orElseThrow(()-> new BizException(\"不支持此登录类型\")); }}
3. 创建自定义登录接口(关键)
@RestController@RequestMapping(\"/token\")@Slf4j@RequiredArgsConstructor(onConstructor = @__(@Autowired))public class AuthController { private final TokenStore tokenStore; private final TokenEndpoint tokenEndpoint; private final RedisTemplate redisTemplate; /** * 自定义登录接口 * @return */ @PostMapping(\"login\") public ResultData login(@RequestBody LoginRequest loginRequest) throws HttpRequestMethodNotSupportedException { Assert.isTrue(StringUtils.isNotEmpty(loginRequest.getGrantType()), \"请在参数中指定登录类型grantType\"); LoginTypeEnum typeEnum = LoginTypeEnum.fromGrantType(loginRequest.getGrantType()); //注入clientId 和 password // 可以通过Header传入client 和 secret User clientUser = new User(\"jianzh5\", \"jianzh5\", new ArrayList()); Authentication token = new UsernamePasswordAuthenticationToken(clientUser, null, new ArrayList()); //构建密码登录 Map map = new HashMap(); switch (typeEnum){ case PASSWORD : { map.put(\"username\", loginRequest.getUserName()); map.put(\"password\", loginRequest.getPassword()); map.put(\"grant_type\", \"password\"); break; } case SMSCODE:{ map.put(\"smsCode\", loginRequest.getSmsCode()); map.put(\"mobile\", loginRequest.getMobile()); map.put(\"grant_type\", \"sms_code\"); break; } default: throw new BizException(\"不支持的登录类型\"); } OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(token,map).getBody(); return ResultData.success(oAuth2AccessToken); } ...}
这里我们将TokenEndpoint注入,然后伪装一个客户端的认证流程,调用TokenEndpoint.postAccessToken()获取接口。
这里我们写死了client信息,实际上也可以通过Header请求头传入或者通过配置文件注入。
4. 在安全配置类中放行登录接口
@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { ... @Override protected void configure(HttpSecurity http) throws Exception { // 加入验证码登陆 http.apply(smsCodeSecurityConfig); http .authorizeRequests().requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll() .and() .authorizeRequests().antMatchers(\"/token/**\",\"/sms/**\").permitAll() .anyRequest().authenticated() .and() .csrf() .disable(); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers( \"/error\", \"/static/**\", \"/v2/api-docs/**\", \"/swagger-resources/**\", \"/webjars/**\", \"/favicon.ico\" ); }}
这个安全配置类中有两个放行策略,一个通过permitAll()实现,一个通过web.ignoring()实现,他们两个的区别是:
web ignoring()比较适合配置前端相关的静态资源,它是完全绕过spring security得所有filter的;permitAll(),会给没有登录的用户适配一个AnonymousAuthenticationToken,设置到SecurityContextHolder,方便后面的filter可以统一处理authentication。
{\"userName\":\"zhangjian\",\"password\":\"111111\",\"grantType\":\"password\",\"mobile\":\"18888887777\",\"smsCode\":\"666666\"}
测试
1. 自定义密码登录
2. 自定义短信验证码登录
3. 不支持的登录类型
小结
本文提供的方案是将登录接口与认证服务器放在一起,如果在项目中由于某些原因不方便将其放在认证服务中,也可以让认证服务器提供一个Feign接口,然后让后端服务调用此接口进行登录即可。
来源:公众号——JAVA日知录
相关文章
- 10-06 英超pfa最佳阵容(pfa英超最佳阵容是官方的)
- 10-06 易建联cba(易建联cba首秀完整视频)
- 10-06 今天世界杯有多少场比赛(今天世界杯有多少场比赛一一
- 10-06 优酷怎么投屏到电视上,优酷怎么将电视投屏到电视上?
- 10-06 优酷怎么关闭弹幕,优酷在那里关闭弹幕?
- 10-06 优酷怎么关闭历史记录,优酷怎么在历史记录过滤短视频
- 10-06 抖音火山版和抖音的区别 抖音怎么授权抖音火山版
- 10-06 抖音月付怎样分期付款 抖音商城怎么设置收货地址
- 10-06 抖音ai绘画怎么弄,抖音如何拍摄ai绘画特效?
- 10-06 据透露,哈登与76人队总裁的关系已经破裂,前者还想
- 10-06 官方:火箭新秀惠特莫尔当选2023年夏季联赛MVP
- 10-06 利拉德交易的一部分?约维奇:NBA 是一门生意
- 10-06 苏亚雷斯为什么喜欢咬人(为什么苏亚雷斯喜欢咬人)
- 10-06 2013年斯诺克世锦赛总决赛(2013年斯诺克世锦
- 10-06 阿根廷女足第一点(阿根廷女足)
- 10-06 尤文图斯和皇马都在关注罗马年轻中场卡佩罗认为他是意
- 10-06 尤文图斯官方确认今年夏天将前往中国热身!对阵国际米
- 10-06 AC米兰想从利物浦挖走洛夫伦,罗马和那不勒斯也想—
- 10-06 乌戈
- 10-06 汉密尔顿:活塞阵容非常好,年轻球员需要时间成长
- 最近发表