好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringSecurity学习之自定义过滤器的实现代码

我们系统中的认证场景通常比较复杂,比如说用户被锁定无法登录,限制登录ip等。而springsecuriy最基本的是基于用户与密码的形式进行认证,由此可知它的一套验证规范根本无法满足业务需要,因此扩展势在必行。那么我们可以考虑自己定义filter添加至springsecurity的 过滤器 栈当中,来实现我们自己的验证需要。

本例中,基于前篇的数据库的student表来模拟一个简单的例子:当student的jointime在当天之后,那么才允许登录

一、创建自己定义的filter

我们先在web包下创建好几个包并定义如下几个类

customerauthfilter:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

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,这个filter的作用是对最基本的用户验证的处理,我们必须重写attemptauthentication方法。authentication接口表示授权接口,通常情况下业务认证通过时会返回一个这个对象。super.setcontinuechainbeforesuccessfulauthentication(true) 设置成true的话,会交给其他过滤器处理。

二、定义userjointimeauthentication

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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;

   }

}

自定义授权方式,在这里接收username的值处理,其中getprincipal我们可以用来存放登录名,getcredentials可以存放密码,这些方法来自于authentication接口

三、定义authenticationprovider

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

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());

   }

}

authenticationmanager会委托authenticationprovider进行授权处理,在这里我们需要重写support方法,该方法定义provider支持的授权对象,那么在这里我们是对userjointimeauthentication处理。

四、websecurityconfig

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

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);

   }

}

在这里面我们通过httpsecurity的方法来添加我们自定义的filter,一定要注意先后顺序。在authenticationmanagerbuilder当中还需要添加我们刚才定义的authenticationprovider

启动成功后,我们将student表里的jointime值改为早于今天的时间,进行登录可以发现:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

原文链接:https://www.cnblogs.com/niechen/p/9174096.html

查看更多关于SpringSecurity学习之自定义过滤器的实现代码的详细内容...

  阅读:11次