1. 程式人生 > >SpringSecurity學習之自定義過濾器

SpringSecurity學習之自定義過濾器

  我們系統中的認證場景通常比較複雜,比如說使用者被鎖定無法登入,限制登入IP等。而SpringSecuriy最基本的是基於使用者與密碼的形式進行認證,由此可知它的一套驗證規範根本無法滿足業務需要,因此擴充套件勢在必行。那麼我們可以考慮自己定義filter新增至SpringSecurity的過濾器棧當中,來實現我們自己的驗證需要。

  本例中,基於前篇的資料庫的Student表來模擬一個簡單的例子:當Student的jointime在當天之後,那麼才允許登入

一、建立自己定義的Filter

我們先在web包下建立好幾個包並定義如下幾個類

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; } }
View Code

  該類繼承AbstractAuthenticationProcessingFilter,這個filter的作用是對最基本的使用者驗證的處理,我們必須重寫attemptAuthentication方法。Authentication介面表示授權介面,通常情況下業務認證通過時會返回一個這個物件。super.setContinueChainBeforeSuccessfulAuthentication(true) 設定成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;
    }
}
View Code

自定義授權方式,在這裡接收username的值處理,其中getPrincipal我們可以用來存放登入名,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;

/**
 * 基本的驗證方式
 *
 * @author chen.nie
 * @date 2018/6/12
 **/
public class UserJoinTimeAuthenticationProvider implements AuthenticationProvider {
    private UserDetailsService userDetailsService;

    public UserJoinTimeAuthenticationProvider(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    /**
     * 認證授權,如果jointime在當前時間之後則認證通過
     * @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的認證
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.getName().equals(UserJoinTimeAuthentication.class.getName());
    }
}
View Code

   AuthenticationManager會委託AuthenticationProvider進行授權處理,在這裡我們需要重寫support方法,該方法定義Provider支援的授權物件,那麼在這裡我們是對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的相關配置
 *
 * @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.配置靜態資源不進行授權驗證
            2.登入地址及跳轉過後的成功頁不需要驗證
            3.其餘均進行授權驗證
         */
        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 {
        //設定自定義userService
        auth.userDetailsService(userService);
        auth.authenticationProvider(new UserJoinTimeAuthenticationProvider(userService));
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }
}
View Code

  在這裡面我們通過HttpSecurity的方法來新增我們自定義的filter,一定要注意先後順序。在AuthenticationManagerBuilder當中還需要新增我們剛才定義的 AuthenticationProvider

啟動成功後,我們將Student表裡的jointime值改為早於今天的時間,進行登入可以發現:

相關推薦

SpringSecurity學習定義過濾器

  我們系統中的認證場景通常比較複雜,比如說使用者被鎖定無法登入,限制登入IP等。而SpringSecuriy最基本的是基於使用者與密碼的形式進行認證,由此可知它的一套驗證規範根本無法滿足業務需要,因此擴充套件勢在必行。那麼我們可以考慮自己定義filter新增至SpringSecurity的過濾器棧當中,來實

Django學習筆記定義過濾器及標籤

目錄結構: 在專案目錄下 建立個名為common的Python包 將common加入到settings檔案中的INSTALLED_APP列表中 INSTALLED_APPS = [ '

springboot定義過濾器

1.public class Logfilter implements Filter{ private Logger logger= LoggerFactory.getLogger(Logfilter.class); @Override public void init(FilterCo

C++學習定義型別

我們在C語言裡面學習了結構體,在C++中的結構體和C中的結構體不一樣。C++允許新增建構函式,成員方法,訪問許可權等等。在C++中還有一種型別叫做類,也可以有成員方法,訪問許可權和建構函式,成員變數等等。那麼這之間有什麼區別呢?其實沒有區別,唯一的區別就是在不宣告許可權的時候預設許可權問題。

安卓開發學習定義Toast的實現

背景 吐司提示很常見,但系統的吐司有一個缺點,就是顯示時長不能自定義,而自定義Toast可以實現這一點   實現步驟 整體思路是:活動視窗發出彈出吐司請求,然後中間層接收請求,發給排程層,排程層顯示吐司 這裡請求的傳遞就是方法的呼叫,顯示和消除吐司的關鍵是呼叫windo

vivado學習定義IP和呼叫定義IP和的步驟

一、自定義IP核 1、開啟 VIVADO 軟體,新建一個工程。 2、Flow Navigater下,單擊 Add Source,選擇 Add or Creat design Sources,然後單擊 Next。 3、單擊 Create File,輸入檔名,單擊 OK。 4、

Mybatis學習定義typeHandler

自定義typeHandler背景比如儲存到資料庫時,有以下需求:1.有個列舉型別的值,想要儲存到資料庫為字串或整數2.Date型別存入資料庫為毫秒數3.物件中的集合(List)屬性儲存資料庫為{xxx,xxx,xxx}的格式,讀取出來自動轉車List傳統的讀取操作也能達到這個

SpringBoot+Shiro學習定義攔截器管理線上使用者(踢出使用者)

應用場景 我們經常會有用到,當A 使用者在北京登入 ,然後A使用者在天津再登入 ,要踢出北京登入的狀態。如果使用者在北京重新登入,那麼又要踢出天津的使用者,這樣反覆。又或是需要限制同一使用者的同時線上數量,超出限制後,踢出最先登入的或是踢出最後登入的。 第一

【本人禿頂程式設計師】Nginx學習定義訪問日誌

←←←←←←←←←←←← 快,點關注! 寫在開始 日誌的重要性不言而喻,一般來說我們開發過程中會為每個專案定義自己的日誌格式以及儲存路徑。 就我們普通的JAVAWEB專案來說,重要的日誌一般輸出並存放在Tomcat的log目錄下,並區分日誌輸出級別。用於區分,查閱並統計相關日誌資

Android學習定義TextWatcher來監聽文字最大輸入字數

開發中有種很可能會遇到的需求就是限制EditText的文字輸入字數,例如微博就限制140字,如果只是限制輸入的字數的話很簡單,EditText有個屬性叫android:maxLength,設定140就

spring 整合shiro 定義過濾器

最近一段時間,我一直在將shiro整合到我的一個專案中,用作認證和授權處理。             shiro對我來說是個新東西,以下是我學習過的內容: http://www.ibm.com/developerworks/cn/java/j-lo-sh

Android學習 定義屬性及TypedArray的用法

  一、 背景說明:           在xml檔案裡定義控制元件的屬性,我們用的最多的是 Android系統自帶的屬性如: <ImageView android:id="@+id/iv_icon" android

百度地圖JavaScript API 學習定義標註圖示(二)

地圖繪製之新增自定義標註圖示(二) 官方提供了兩種方法來自定義標註圖示: 通過引數MarkerOptions的icon屬性進行設定 使用Marker.setIcon()方法。 第二

Caffe學習定義建立新的Layer層

caffe原始碼中已經幫我封裝好了各種各樣的layer,但是有時候現有的layer不能滿足設計的網路要求,這個時候需要自己定義一個新的layer,本文參考here,進行簡單講解,具體方式如下: 一.建立.hpp檔案 1.新增你的layer標頭檔案置

ClassLoader學習 定義classLoader和雙親委派原理

ClassLoader學習之  自定義classLoader和雙親委派原理1、ClassLoader原理介紹​ ClassLoader使用的是雙親委託模型來搜尋類的,每個ClassLoad

大數據學習定義輸入 13

table 輸入 配置信息 tst float 分享 ado 自定義 throws 一:自定義輸出 需求:將多個小文件合並為SequenceFile(存儲了多個小文件) 存儲格式:文件路徑+文件的內容 c:/a.txt i am hunter henshu

大數據學習定義輸出 13

系統 java pub 什麽 rri args sda stream out 二:自定義輸出 自定義輸出 需求:過濾日誌文件 把包含itstaredu的放在一個文件中 d:/itstaredu.log 把不包含itstaredu的放在另外一個文件 d:/oth

SpringSecurity系列定義登入驗證成功與失敗的結果處理

一、需要自定義登入結果的場景 在我之前的文章中,做過登入驗證流程的原始碼解析。其中比較重要的就是 當我們登入成功的時候,是由AuthenticationSuccessHandler進行登入結果處理,預設跳轉到defaultSuccessUrl配置的路徑對應的資源頁面(一般是首頁index.html)。 當我

springSecurity新增定義過濾器

        我們知道,springSecurity其實就是將過濾器和aop進行整合。其實我們也可以新增自己的過濾器。        很簡單,配置如下<http use-expressions=

vue2.0學習筆記定義組件

2.0 sco ron 自定義組件 定義 temp use 使用 imp step one: 推薦結構 step two: Loading.vue <template> <h3>{{msg}}<