若依登录⾃定义扩展Springboot+security⽀持密码、⼿机验证码登录⽅式
若依开源框架登录使⽤的配置⼤部分都是security⾃定义的,⽬前希望在此框架基础上⽀持⾃定义的登录,如⼿机号+密码登录认证、⼿机号+短信验证码认证。
1、⾃定义登录实现思路
主要是实现继承DaoAuthenticationProvider类,重写additionalAuthenticationChecks⽅法,将通过密码标识来判断是不是需要验证密码和免密验证。
2、继承DaoAuthenticationProvider
`import org.AuthenticationException;
import org.userdetails.UserDetails;
import org.userdetails.UserDetailsService;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.pto.bcrypt.BCryptPasswordEncoder;
/**
短信登陆鉴权 Provider,要求实现 AuthenticationProvider 接⼝
*/
public class SmsCodeAuthenticationProvider extends DaoAuthenticationProvider {
public SmsCodeAuthenticationProvider(UserDetailsService userDetailsService) {
super();
setUserDetailsService(userDetailsService);
}
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (Credentials() == null) {
this.logger.debug(“Authentication failed: no credentials provided”);
throw new
Message(“AbstractUserDetailsAuthenticationProvider.badCredentials”,“Bad credentials”));
} else {
String presentedPassword = Credentials().toString();
if(“CUSTOM_LOGIN_SMS”.equals(presentedPassword)){
//短信登录,不验证密码
}else{
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
if (!passwordEncoder.matches(presentedPassword, Password())) {
this.logger.debug(“Authentication failed: password does not match stored value”);
throw new
Message(“AbstractUserDetailsAuthenticationProvider.badCredentials”,“Bad credentials”));
}
}
}
}
}`
3、修改security配置,修改SecurityConfig中的⾝份验证接⼝,加⼊重写的authenticationProvider⽅法
/** * ⾝份认证接⼝ */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(new SmsCodeAuthenticationProvider(userDetailsService));
auth.userDetailsService(userDetailsService) .passwordEncoder(bCryptPasswordEncoder()); }
并添加你的登录接⼝匿名访问
4、实现登录接⼝
controller类,通过⼿机号获取到存在redis中的验证码,若获取不到则返回验证码失效
@ApiOperation("⼿机号+短信验证码登录") @PostMapping(value="/smslogin") public AjaxResult loginByCode(@RequestBody LoginBody body) { String realAuthCode = CacheObject(REDIS_KEY_PREFIX_AUTH_CODE + Phone()); if(StringUtils.isEmpty(realAuthCode)){ ("验证码失效"); } else if(!Code().equals(realAuthCode)) { ("验证码错误"); } else { SysUser entity = userService.Phone()); String token = smsLoginService.Phone(), "CUSTOM_LOGIN_SMS"); AjaxResult result = AjaxResult.success("登录成功!", entity); result.put(Constants.TOKEN, token); //登陆成功后清除redis缓存
RedisCache.deleteObject(REDIS_KEY_PREFIX_AUTH_CODE + Phone()); return result; } }
5.如果你的⽤户表的⽤户名与⼿机号不相同则可以在UserDetailsServiceImpl中添加如下代码
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundE
xception { SysUser user; if(Patternpile("^[1] [3,4,5,7,8][0-9]{9}$").matcher(username).matches()){ user = userService.selectUserByPhone(username); }else{ user =
userService.selectUserByUserName(username); } if (StringUtils.isNull(user)) { log.info("登录⽤户:{} 不存在.", username); throw new UsernameNotFoundException("登录⽤户:" + username + " 不存在"); } else if (Code().DelFlag())) { log.info("登录⽤户:{} 已被删除.", username); throw new BaseException("对不起,您的账号:" + username + " 已被删除"); } else if
手机密码(Code().Status())) { log.info("登录⽤户:{} 已被停⽤.", username); throw new BaseException("对不起,您的账号:" + username + " 已停⽤"); } return createLoginUser(user); }
通过正则表达式来判断传过来的是⽤户名还是⼿机号,通过不同的查询来获取⽤户数据
6.调⽤接⼝测试短信发送和登陆是否成功
⾸次发布⽂章,有不⾜之处或代码有存在问题的地⽅请各位指教
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论