說明 springboot 版本 2.0.3
源碼地址:點擊跳轉
系列
緊接着上一篇,上一篇中登錄驗證都由 security 幫助我們完成了,如果我們想要增加一個驗證碼登錄或者其它的自定義校驗就沒辦法了,因此這一篇講解如何實現這個功能。
一、 實現自定義登錄校驗類
繼承 UsernamePasswordAuthenticationFilter 類來拓展登錄校驗,代碼如下:
public class MyUsernamePasswordAuthentication extends UsernamePasswordAuthenticationFilter{
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
//我們可以在這里進行額外的驗證,如果驗證失敗拋出繼承AuthenticationException的自定義錯誤。
log.info("在這里進行驗證碼判斷");
//只要最終的驗證是賬號密碼形式就無需修改后續過程
return super.attemptAuthentication(request, response);
}
@Override
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
// TODO Auto-generated method stub
super.setAuthenticationManager(authenticationManager);
}
}
二、 將自定義登錄配置到 security 中
編寫自定義登錄過濾器后,configure Bean 修改為如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf() //跨站
.disable() //關閉跨站檢測
//自定義鑒權過程,無需下面設置
.authorizeRequests()//驗證策略
.antMatchers("/public/**").permitAll()//無需驗證路徑
.antMatchers("/user/**").permitAll()
.antMatchers("/login").permitAll()//放行登錄
.antMatchers(HttpMethod.GET, "/user").hasAuthority("getAllUser")//擁有權限才可訪問
.antMatchers(HttpMethod.GET, "/user").hasAnyAuthority("1","2")//擁有任一權限即可訪問
//角色類似,hasRole(),hasAnyRole()
.anyRequest().authenticated()
.and()
//自定義異常處理
.exceptionHandling()
.authenticationEntryPoint(myAuthenticationEntryPoint)//未登錄處理
.accessDeniedHandler(myAccessDeniedHandler)//權限不足處理
.and()
//加入自定義登錄校驗
.addFilterBefore(myUsernamePasswordAuthentication(),UsernamePasswordAuthenticationFilter.class)
.rememberMe()//默認放在內存中
.rememberMeServices(rememberMeServices())
.key("INTERNAL_SECRET_KEY")
// 重寫usernamepasswordauthenticationFilter后,下面的formLogin()設置將失效,需要手動設置到個性化過濾器中
// .and()
// .formLogin()
// .loginPage("/public/unlogin") //未登錄跳轉頁面,設置了authenticationentrypoint后無需設置未登錄跳轉頁面
// .loginProcessingUrl("/public/login")//登錄api
// .successForwardUrl("/success")
// .failureForwardUrl("/failed")
// .usernameParameter("id")
// .passwordParameter("password")
// .failureHandler(myAuthFailedHandle) //登錄失敗處理
// .successHandler(myAuthSuccessHandle)//登錄成功處理
// .usernameParameter("id")
.and()
.logout()//自定義登出
.logoutUrl("/public/logout")
.logoutSuccessUrl("public/logoutSuccess")
.logoutSuccessHandler(myLogoutSuccessHandle);
}
然后再編寫 Bean,代碼如下:
@Bean
public MyUsernamePasswordAuthentication myUsernamePasswordAuthentication(){
MyUsernamePasswordAuthentication myUsernamePasswordAuthentication = new MyUsernamePasswordAuthentication();
myUsernamePasswordAuthentication.setAuthenticationFailureHandler(myAuthFailedHandle); //設置登錄失敗處理類
myUsernamePasswordAuthentication.setAuthenticationSuccessHandler(myAuthSuccessHandle);//設置登錄成功處理類
myUsernamePasswordAuthentication.setFilterProcessesUrl("/public/login");
myUsernamePasswordAuthentication.setRememberMeServices(rememberMeServices()); //設置記住我
myUsernamePasswordAuthentication.setUsernameParameter("id");
myUsernamePasswordAuthentication.setPasswordParameter("password");
return myUsernamePasswordAuthentication;
}
完成。