SpringSecurity學(xué)習(xí)之自定義過(guò)濾器的實(shí)現(xiàn)代碼
我們系統(tǒng)中的認(rèn)證場(chǎng)景通常比較復(fù)雜,比如說(shuō)用戶被鎖定無(wú)法登錄,限制登錄IP等。而SpringSecuriy最基本的是基于用戶與密碼的形式進(jìn)行認(rèn)證,由此可知它的一套驗(yàn)證規(guī)范根本無(wú)法滿足業(yè)務(wù)需要,因此擴(kuò)展勢(shì)在必行。那么我們可以考慮自己定義filter添加至SpringSecurity的過(guò)濾器棧當(dāng)中,來(lái)實(shí)現(xiàn)我們自己的驗(yàn)證需要。
本例中,基于前篇的數(shù)據(jù)庫(kù)的Student表來(lái)模擬一個(gè)簡(jiǎn)單的例子:當(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的作用是對(duì)最基本的用戶驗(yàn)證的處理,我們必須重寫attemptAuthentication方法。Authentication接口表示授權(quán)接口,通常情況下業(yè)務(wù)認(rèn)證通過(guò)時(shí)會(huì)返回一個(gè)這個(gè)對(duì)象。super.setContinueChainBeforeSuccessfulAuthentication(true) 設(shè)置成true的話,會(huì)交給其他過(guò)濾器處理。
二、定義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我們可以用來(lái)存放登錄名,getCredentials可以存放密碼,這些方法來(lái)自于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)證通過(guò)
* @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會(huì)委托AuthenticationProvider進(jìn)行授權(quán)處理,在這里我們需要重寫support方法,該方法定義Provider支持的授權(quán)對(duì)象,那么在這里我們是對(duì)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)過(guò)后的成功頁(yè)不需要驗(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);
}
}
在這里面我們通過(guò)HttpSecurity的方法來(lái)添加我們自定義的filter,一定要注意先后順序。在AuthenticationManagerBuilder當(dāng)中還需要添加我們剛才定義的AuthenticationProvider
啟動(dòng)成功后,我們將Student表里的jointime值改為早于今天的時(shí)間,進(jìn)行登錄可以發(fā)現(xiàn):

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringSecurity的安全過(guò)濾器鏈功能詳解
- SpringSecurity中內(nèi)置過(guò)濾器的使用小結(jié)
- springSecurity自定義登錄接口和JWT認(rèn)證過(guò)濾器的流程
- SpringSecurity中的Filter Chain(過(guò)濾器鏈)
- idea如何debug看springsecurity的過(guò)濾器順序
- SpringSecurity request過(guò)濾問(wèn)題示例小結(jié)
- SpringSecurity定義多個(gè)過(guò)濾器鏈的操作代碼
- springSecurity之如何添加自定義過(guò)濾器
- springSecurity過(guò)濾web請(qǐng)求的項(xiàng)目實(shí)踐
相關(guān)文章
SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法
這篇文章主要介紹了SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
Maven打包jar包沒(méi)有主屬性問(wèn)題解決方案
這篇文章主要介紹了Maven打包jar包沒(méi)有主屬性問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Spring Cloud重試機(jī)制與各組件的重試總結(jié)
這篇文章主要給大家介紹了關(guān)于Spring Cloud中重試機(jī)制與各組件的重試的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
Java中的可重入鎖ReentrantLock簡(jiǎn)析
這篇文章主要介紹了Java中的可重入鎖ReentrantLock簡(jiǎn)析,可重入是指同一個(gè)線程如果首次獲得了這把鎖,那么因?yàn)樗沁@把鎖的擁有者,因此有權(quán)利再次獲取這把鎖如果是不可重入鎖,那么第二次獲得鎖時(shí),自己也會(huì)被鎖擋住,需要的朋友可以參考下2023-12-12
Java 獲取當(dāng)前時(shí)間及實(shí)現(xiàn)時(shí)間倒計(jì)時(shí)功能【推薦】
這篇文章主要介紹了Java 獲取當(dāng)前時(shí)間及實(shí)現(xiàn)時(shí)間倒計(jì)時(shí)功能 ,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05
Java 泛型 Generic機(jī)制實(shí)例詳解
這篇文章主要為大家介紹了Java 泛型 Generic機(jī)制實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Spring boot + LayIM + t-io 實(shí)現(xiàn)文件上傳、 監(jiān)聽(tīng)用戶狀態(tài)的實(shí)例代碼
這篇文章主要介紹了Spring boot + LayIM + t-io 實(shí)現(xiàn)文件上傳、 監(jiān)聽(tīng)用戶狀態(tài)的實(shí)例代碼,需要的朋友可以參考下2017-12-12
Mybatis-plus出現(xiàn)數(shù)據(jù)庫(kù)id很大或者為負(fù)數(shù)的解決
本文主要介紹了Mybatis-plus出現(xiàn)數(shù)據(jù)庫(kù)id很大或者為負(fù)數(shù)的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02

