SpringSecurity學(xué)習(xí)之自定義過濾器的實(shí)現(xiàn)代碼
我們系統(tǒng)中的認(rèn)證場景通常比較復(fù)雜,比如說用戶被鎖定無法登錄,限制登錄IP等。而SpringSecuriy最基本的是基于用戶與密碼的形式進(jìn)行認(rèn)證,由此可知它的一套驗(yàn)證規(guī)范根本無法滿足業(yè)務(wù)需要,因此擴(kuò)展勢在必行。那么我們可以考慮自己定義filter添加至SpringSecurity的過濾器棧當(dāng)中,來實(shí)現(xiàn)我們自己的驗(yàn)證需要。
本例中,基于前篇的數(shù)據(jù)庫的Student表來模擬一個(gè)簡單的例子:當(dāng)Student的jointime在當(dāng)天之后,那么才允許登錄
一、創(chuàng)建自己定義的Filter
我們先在web包下創(chuàng)建好幾個(gè)包并定義如下幾個(gè)類
CustomerAuthFilter:
package com.bdqn.lyrk.security.study.web.filter; import com.bdqn.lyrk.security.study.web.authentication.UserJoinTimeAuthentication; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class CustomerAuthFilter extends AbstractAuthenticationProcessingFilter { private AuthenticationManager authenticationManager; public CustomerAuthFilter(AuthenticationManager authenticationManager) { super(new AntPathRequestMatcher("/login", "POST")); this.authenticationManager = authenticationManager; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { String username = request.getParameter("username"); UserJoinTimeAuthentication usernamePasswordAuthenticationToken =new UserJoinTimeAuthentication(username); Authentication authentication = this.authenticationManager.authenticate(usernamePasswordAuthenticationToken); if (authentication != null) { super.setContinueChainBeforeSuccessfulAuthentication(true); } return authentication; } }
該類繼承AbstractAuthenticationProcessingFilter,這個(gè)filter的作用是對最基本的用戶驗(yàn)證的處理,我們必須重寫attemptAuthentication方法。Authentication接口表示授權(quán)接口,通常情況下業(yè)務(wù)認(rèn)證通過時(shí)會返回一個(gè)這個(gè)對象。super.setContinueChainBeforeSuccessfulAuthentication(true) 設(shè)置成true的話,會交給其他過濾器處理。
二、定義UserJoinTimeAuthentication
package com.bdqn.lyrk.security.study.web.authentication; import org.springframework.security.authentication.AbstractAuthenticationToken; public class UserJoinTimeAuthentication extends AbstractAuthenticationToken { private String username; public UserJoinTimeAuthentication(String username) { super(null); this.username = username; } @Override public Object getCredentials() { return null; } @Override public Object getPrincipal() { return username; } }
自定義授權(quán)方式,在這里接收username的值處理,其中g(shù)etPrincipal我們可以用來存放登錄名,getCredentials可以存放密碼,這些方法來自于Authentication接口
三、定義AuthenticationProvider
package com.bdqn.lyrk.security.study.web.authentication; import com.bdqn.lyrk.security.study.app.pojo.Student; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import java.util.Date; /** * 基本的驗(yàn)證方式 * * @author chen.nie * @date 2018/6/12 **/ public class UserJoinTimeAuthenticationProvider implements AuthenticationProvider { private UserDetailsService userDetailsService; public UserJoinTimeAuthenticationProvider(UserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } /** * 認(rèn)證授權(quán),如果jointime在當(dāng)前時(shí)間之后則認(rèn)證通過 * @param authentication * @return * @throws AuthenticationException */ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = (String) authentication.getPrincipal(); UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if (!(userDetails instanceof Student)) { return null; } Student student = (Student) userDetails; if (student.getJoinTime().after(new Date())) return new UserJoinTimeAuthentication(username); return null; } /** * 只處理UserJoinTimeAuthentication的認(rèn)證 * @param authentication * @return */ @Override public boolean supports(Class<?> authentication) { return authentication.getName().equals(UserJoinTimeAuthentication.class.getName()); } }
AuthenticationManager會委托AuthenticationProvider進(jìn)行授權(quán)處理,在這里我們需要重寫support方法,該方法定義Provider支持的授權(quán)對象,那么在這里我們是對UserJoinTimeAuthentication處理。
四、WebSecurityConfig
package com.bdqn.lyrk.security.study.app.config; import com.bdqn.lyrk.security.study.app.service.UserService; import com.bdqn.lyrk.security.study.web.authentication.UserJoinTimeAuthenticationProvider; import com.bdqn.lyrk.security.study.web.filter.CustomerAuthFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; /** * spring-security的相關(guān)配置 * * @author chen.nie * @date 2018/6/7 **/ @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserService userService; @Override protected void configure(HttpSecurity http) throws Exception { /* 1.配置靜態(tài)資源不進(jìn)行授權(quán)驗(yàn)證 2.登錄地址及跳轉(zhuǎn)過后的成功頁不需要驗(yàn)證 3.其余均進(jìn)行授權(quán)驗(yàn)證 */ http. authorizeRequests().antMatchers("/static/**").permitAll(). and().authorizeRequests().antMatchers("/user/**").hasRole("7022"). and().authorizeRequests().anyRequest().authenticated(). and().formLogin().loginPage("/login").successForwardUrl("/toIndex").permitAll() .and().logout().logoutUrl("/logout").invalidateHttpSession(true).deleteCookies().permitAll() ; http.addFilterBefore(new CustomerAuthFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //設(shè)置自定義userService auth.userDetailsService(userService); auth.authenticationProvider(new UserJoinTimeAuthenticationProvider(userService)); } @Override public void configure(WebSecurity web) throws Exception { super.configure(web); } }
在這里面我們通過HttpSecurity的方法來添加我們自定義的filter,一定要注意先后順序。在AuthenticationManagerBuilder當(dāng)中還需要添加我們剛才定義的AuthenticationProvider
啟動成功后,我們將Student表里的jointime值改為早于今天的時(shí)間,進(jìn)行登錄可以發(fā)現(xiàn):
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解決springboot項(xiàng)目啟動報(bào)錯(cuò)Field xxxMapper in com...xx
這篇文章主要介紹了解決springboot項(xiàng)目啟動報(bào)錯(cuò)Field xxxMapper in com...xxxContr問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12java獲取文件擴(kuò)展名的方法小結(jié)【正則與字符串截取】
這篇文章主要介紹了java獲取文件擴(kuò)展名的方法,結(jié)合實(shí)例形式分析了使用正則與字符串截取兩種獲取擴(kuò)展名的操作技巧,需要的朋友可以參考下2017-01-01Java流操作之?dāng)?shù)據(jù)流實(shí)例代碼
這篇文章主要介紹了Java流操作之?dāng)?shù)據(jù)流實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Java基于Swing和netty實(shí)現(xiàn)仿QQ界面聊天小項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了Java如何利用Swing和netty實(shí)現(xiàn)仿QQ界面聊天小項(xiàng)目,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-09-09JAVA使用動態(tài)代理對象進(jìn)行敏感字過濾代碼實(shí)例
這篇文章主要介紹了JAVA使用動態(tài)代理對象進(jìn)行敏感字過濾代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09Eclipse中安裝反編譯工具Fernflower的方法(Enhanced Class Decompiler)
這篇文章主要介紹了Eclipse中安裝反編譯工具Fernflower的方法(Enhanced Class Decompiler),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01Java實(shí)現(xiàn)FTP文件的上傳和下載功能的實(shí)例代碼
FTP 是File Transfer Protocol(文件傳輸協(xié)議)的英文簡稱,而中文簡稱為“文傳協(xié)議”。接下來通過本文給大家實(shí)例講解Java實(shí)現(xiàn)FTP文件的上傳和下載功能,需要的的朋友一起看看吧2016-11-11java使用XSSFWorkbook實(shí)現(xiàn)讀寫Excel
這篇文章主要為大家詳細(xì)介紹了java如何通過使用XSSFWorkbook實(shí)現(xiàn)讀寫Excel功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04