開(kāi)發(fā)遇到一件很尷尬的事情,springboot里面使用security做登錄驗(yàn)證,但是默認(rèn)的就是驗(yàn)證username和password阶冈,現(xiàn)在的第三方或者短信登錄非常流行闷尿。我現(xiàn)在的需求是做賬號(hào)+短信登錄(ps:后面還不知道要加啥... so:舊的不能廢,只能擴(kuò)展
)女坑,接rongcloud sdk
post:/login
params:{
username:mobile,
sessionid:rongcloud_sessionid,
code:驗(yàn)證碼
}
我的想法如標(biāo)題填具,于是開(kāi)始找各種娘、哥匆骗。灌旧。。绰筛。枢泰。
這個(gè)時(shí)候度娘都不起作用了o(╥﹏╥)o,谷哥了半天也沒(méi)詳細(xì)的解決方案
大多都是使用的xml方式配置
我想用的是springboot 注解(ー`′ー)
最終不知道把誰(shuí)和誰(shuí)的想法揉在了一起(尷尬)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
//-------------------------------①----------------------------------
@Autowired
private UserDetailsService userDetailsService;
//-------------------------------①----------------------------------
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetailsService userDetailsService= //自定義或者使用①
auth.authenticationProvider(new LoginAuthenticationProvider(userDetailsService));
//這東西千萬(wàn)不能忘
auth.userDetailsService(userDetailsService)
.passwordEncoder(new Md5PasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
...
// 加入自定義UsernamePasswordAuthenticationFilter替代原有Filter
http.addFilterAt(
new ApiUsernamePasswordAuthenticationFilter(super.authenticationManager()),
UsernamePasswordAuthenticationFilter.class);
...
}
...
}
自定義LoginAuthenticationProvider繼承DaoAuthenticationProvider重寫(xiě)additionalAuthenticationChecks()這里就是做密碼比較的
public class LoginAuthenticationProvider extends DaoAuthenticationProvider {
public LoginAuthenticationProvider(UserDetailsService userDetailsService) {
super();
// 這個(gè)地方一定要對(duì)userDetailsService賦值铝噩,不然userDetailsService是null (這個(gè)坑有點(diǎn)深)
setUserDetailsService(userDetailsService);
}
@SuppressWarnings("deprecation")
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
Object salt = null;
if (this.getSaltSource() != null) {
salt = this.getSaltSource().getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(
messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
//我就改了這個(gè)地方衡蚂,增加一個(gè)驗(yàn)證碼登錄標(biāo)識(shí)(具體怎么做就看自己了)
// 【原本的是登錄密碼和數(shù)據(jù)密碼不等就拋出異常,我用驗(yàn)證碼登錄時(shí)壓根都不知道密碼(ー`′ー)】
//so 我給短信登錄時(shí)賦值一個(gè)默認(rèn)密碼(驗(yàn)證碼登錄標(biāo)識(shí))來(lái)判斷骏庸,不讓這兒報(bào)異常
if (!presentedPassword.equals("YZMLG_KSssdS1D145Sd4S")) {
if (!getPasswordEncoder().isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
}
}
至于這個(gè) #驗(yàn)證碼登錄標(biāo)識(shí)# 怎么來(lái)的就在下面
自定義的Filter
public class ApiUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public ApiUsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
super(new AntPathRequestMatcher("/login", "POST"));
...
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
....
//驗(yàn)證碼登錄
if(passcode!=null){
if(sessionid!=null){
try {
//接rongcloud sdk 驗(yàn)證
SMSVerifyCodeResult result = smsWapper.verifyCode(sessionid, passcode);
if (result.getCode() == 200 && result.getSuccess()) {//驗(yàn)證成功
password = "YZMLG_KSssdS1D145Sd4S";//驗(yàn)證碼登錄標(biāo)識(shí)
}else{
throw new SessionAuthenticationException("驗(yàn)證碼錯(cuò)誤");
}
} catch (Exception e) {
e.printStackTrace();
throw new SessionAuthenticationException("驗(yàn)證碼錯(cuò)誤");
}
}
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
....
return this.getAuthenticationManager().authenticate(authRequest);
}
}
大概的就是這樣
恩毛甲,做個(gè)筆記(坑+1)