激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - spring security自定義認證登錄的全過程記錄

spring security自定義認證登錄的全過程記錄

2021-03-09 14:19CatalpaFlat Java教程

這篇文章主要給大家介紹了關于spring security自定義認證登錄的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。

spring security使用分類:

如何使用spring security,相信百度過的都知道,總共有四種用法,從簡到深為:

1、不用數據庫,全部數據寫在配置文件,這個也是官方文檔里面的demo;

2、使用數據庫,根據spring security默認實現代碼設計數據庫,也就是說數據庫已經固定了,這種方法不靈活,而且那個數據庫設計得很簡陋,實用性差;

3、spring security和acegi不同,它不能修改默認filter了,但支持插入filter,所以根據這個,我們可以插入自己的filter來靈活使用;

4、暴力手段,修改源碼,前面說的修改默認filter只是修改配置文件以替換filter而已,這種是直接改了里面的源碼,但是這種不符合oo設計原則,而且不實際,不可用。

本文主要介紹了關于spring security自定義認證登錄的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

1.概要

1.1.簡介

spring security是一種基于 spring aop 和 servlet 過濾器的安全框架,以此來管理權限認證等。

1.2.spring security 自定義認證流程

1)認證過程

生成未認證的authenticationtoken                 

?
1
2
3
4
5
6
7
8
↑(獲取信息)  (根據authenticationtoken分配provider)    
authenticationfilter -> authenticationmanager -> authenticationprovider
       ↓(認證)
      userdetails(一般查詢數據庫獲取)
       ↓(通過)
       生成認證成功的authenticationtoken
        ↓(存放)
       securitycontextholder

2)將authenticationfilter加入到security過濾鏈(資源服務器中配置),如:

?
1
http.addfilterbefore(authenticationfilter, abstractpreauthenticatedprocessingfilter.class)

或者:

?
1
http.addfilterafter(authenticationfilter, usernamepasswordauthenticationfilter.class)

2.以手機號短信登錄為例

2.1.開發環境

  • springboot
  • spring security
  • redis

2.2.核心代碼分析

2.2.1.自定義登錄認證流程

2.2.1.1.自定義認證登錄token

?
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
/**
 * 手機登錄token
 *
 * @author : catalpaflat
 */
public class mobileloginauthenticationtoken extends abstractauthenticationtoken {
 private static final long serialversionuid = springsecuritycoreversion.serial_version_uid;
 private static final logger logger = loggerfactory.getlogger(mobileloginauthenticationtoken.class.getname());
 private final object principal;
 public mobileloginauthenticationtoken(string mobile) {
 super(null);
 this.principal = mobile;
 this.setauthenticated(false);
 logger.info("mobileloginauthenticationtoken setauthenticated ->false loading ...");
 }
 public mobileloginauthenticationtoken(object principal,
      collection<? extends grantedauthority> authorities) {
 super(authorities);
 this.principal = principal;
 // must use super, as we override
 super.setauthenticated(true);
 logger.info("mobileloginauthenticationtoken setauthenticated ->true loading ...");
 }
 @override
 public void setauthenticated(boolean authenticated) {
 if (authenticated) {
  throw new illegalargumentexception(
   "cannot set this token to trusted - use constructor which takes a grantedauthority list instead");
 }
 super.setauthenticated(false);
 }
 @override
 public object getcredentials() {
 return null;
 }
 @override
 public object getprincipal() {
 return this.principal;
 }
 @override
 public void erasecredentials() {
 super.erasecredentials();
 }
}

注:

setauthenticated():判斷是否已認證

  • 在過濾器時,會生成一個未認證的authenticationtoken,此時調用的是自定義token的setauthenticated(),此時設置為false -> 未認證
  • 在提供者時,會生成一個已認證的authenticationtoken,此時調用的是父類的setauthenticated(),此時設置為true -> 已認證

2.2.1.1.自定義認證登錄過濾器

?
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
/**
 * 手機短信登錄過濾器
 *
 * @author : catalpaflat
 */
public class mobileloginauthenticationfilter extends abstractauthenticationprocessingfilter {
 private boolean postonly = true;
 private static final logger logger = loggerfactory.getlogger(mobileloginauthenticationfilter.class.getname());
 @getter
 @setter
 private string mobileparametername;
 public mobileloginauthenticationfilter(string mobileloginurl, string mobileparametername,
      string httpmethod) {
 super(new antpathrequestmatcher(mobileloginurl, httpmethod));
 this.mobileparametername = mobileparametername;
 logger.info("mobileloginauthenticationfilter loading ...");
 }
 @override
 public authentication attemptauthentication(httpservletrequest request,      httpservletresponse response) throws authenticationexception, ioexception, servletexception {
 if (postonly && !request.getmethod().equals(httpmethod.post.name())) {
  throw new authenticationserviceexception("authentication method not supported: " + request.getmethod());
 }
 //get mobile
 string mobile = obtainmobile(request);
 //assemble token
 mobileloginauthenticationtoken authrequest = new mobileloginauthenticationtoken(mobile);
 
 // allow subclasses to set the "details" property
 setdetails(request, authrequest);
 
 return this.getauthenticationmanager().authenticate(authrequest);
 }
 /**
 * 設置身份認證的詳情信息
 */
 private void setdetails(httpservletrequest request, mobileloginauthenticationtoken authrequest) {
 authrequest.setdetails(authenticationdetailssource.builddetails(request));
 }
 /**
 * 獲取手機號
 */
 private string obtainmobile(httpservletrequest request) {
 return request.getparameter(mobileparametername);
 }
 public void setpostonly(boolean postonly) {
 this.postonly = postonly;
 }
}

注:attemptauthentication()方法:

  • 過濾指定的url、httpmethod
  • 獲取所需請求參數數據封裝生成一個未認證的authenticationtoken
  • 傳遞給authenticationmanager認證

2.2.1.1.自定義認證登錄提供者

?
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
/**
 * 手機短信登錄認證提供者
 *
 * @author : catalpaflat
 */
public class mobileloginauthenticationprovider implements authenticationprovider {
 private static final logger logger = loggerfactory.getlogger(mobileloginauthenticationprovider.class.getname());
 @getter
 @setter
 private userdetailsservice customuserdetailsservice;
 public mobileloginauthenticationprovider() {
 logger.info("mobileloginauthenticationprovider loading ...");
 }
 /**
 * 認證
 */
 @override
 public authentication authenticate(authentication authentication) throws authenticationexception {
 //獲取過濾器封裝的token信息
 mobileloginauthenticationtoken authenticationtoken = (mobileloginauthenticationtoken) authentication;
 //獲取用戶信息(數據庫認證)
 userdetails userdetails = customuserdetailsservice.loaduserbyusername((string) authenticationtoken.getprincipal());
 //不通過
 if (userdetails == null) {
  throw new internalauthenticationserviceexception("unable to obtain user information");
 }
 //通過
 mobileloginauthenticationtoken authenticationresult = new mobileloginauthenticationtoken(userdetails, userdetails.getauthorities());
 authenticationresult.setdetails(authenticationtoken.getdetails());
 
 return authenticationresult;
 }
 /**
 * 根據token類型,來判斷使用哪個provider
 */
 @override
 public boolean supports(class<?> authentication) {
 return mobileloginauthenticationtoken.class.isassignablefrom(authentication);
 }
}

注:authenticate()方法

  • 獲取過濾器封裝的token信息
  • 調取userdetailsservice獲取用戶信息(數據庫認證)->判斷通過與否
  • 通過則封裝一個新的authenticationtoken,并返回

2.2.1.1.自定義認證登錄認證配置

?
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
@configuration(springbeannameconstant.default_custom_mobile_login_authentication_security_config_bn)
public class mobileloginauthenticationsecurityconfig extends securityconfigureradapter<defaultsecurityfilterchain, httpsecurity> {
 private static final logger logger = loggerfactory.getlogger(mobileloginauthenticationsecurityconfig.class.getname());
 @value("${login.mobile.url}")
 private string defaultmobileloginurl;
 @value("${login.mobile.parameter}")
 private string defaultmobileloginparameter;
 @value("${login.mobile.httpmethod}")
 private string defaultmobileloginhttpmethod;
 @autowired
 private customymlconfig customymlconfig;
 @autowired
 private userdetailsservice customuserdetailsservice;
 @autowired
 private authenticationsuccesshandler customauthenticationsuccesshandler;
 @autowired
 private authenticationfailurehandler customauthenticationfailurehandler;
 public mobileloginauthenticationsecurityconfig() {
 logger.info("mobileloginauthenticationsecurityconfig loading ...");
 }
 @override
 public void configure(httpsecurity http) throws exception {
 mobilepojo mobile = customymlconfig.getlogins().getmobile();
 string url = mobile.geturl();
 string parameter = mobile.getparameter().getmobile();
 string httpmethod = mobile.gethttpmethod();
 mobileloginauthenticationfilter mobileloginauthenticationfilter = new mobileloginauthenticationfilter(stringutils.isblank(url) ? defaultmobileloginurl : url,
  stringutils.isblank(parameter) ? defaultmobileloginurl : parameter, stringutils.isblank(httpmethod) ? defaultmobileloginhttpmethod : httpmethod); mobileloginauthenticationfilter.setauthenticationmanager(http.getsharedobject(authenticationmanager.class)); mobileloginauthenticationfilter.setauthenticationsuccesshandler(customauthenticationsuccesshandler); mobileloginauthenticationfilter.setauthenticationfailurehandler(customauthenticationfailurehandler);
 mobileloginauthenticationprovider mobileloginauthenticationprovider = new mobileloginauthenticationprovider(); mobileloginauthenticationprovider.setcustomuserdetailsservice(customuserdetailsservice);
 http.authenticationprovider(mobileloginauthenticationprovider)
  .addfilterafter(mobileloginauthenticationfilter, usernamepasswordauthenticationfilter.class);
 }
}

注:configure()方法

實例化authenticationfilter和authenticationprovider

將authenticationfilter和authenticationprovider添加到spring security中。

2.2.2.基于redis自定義驗證碼校驗

2.2.2.1.基于redis自定義驗證碼過濾器

?
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
/**
 * 驗證碼過濾器
 *
 * @author : catalpaflat
 */
@component(springbeannameconstant.default_validate_code_filter_bn)
public class validatecodefilter extends onceperrequestfilter implements initializingbean {
 private static final logger logger = loggerfactory.getlogger(validatecodefilter.class.getname());
 @autowired
 private customymlconfig customymlconfig;
 @autowired
 private redistemplate<object, object> redistemplate;
 /**
  * 驗證請求url與配置的url是否匹配的工具類
  */
 private antpathmatcher pathmatcher = new antpathmatcher();
 public validatecodefilter() {
  logger.info("loading validatecodefilter...");
 }
 @override
 protected void dofilterinternal(httpservletrequest request, httpservletresponse response,
         filterchain filterchain) throws servletexception, ioexception {
  string url = customymlconfig.getlogins().getmobile().geturl();
  if (pathmatcher.match(url, request.getrequesturi())) {
   string deviceid = request.getheader("deviceid");
   if (stringutils.isblank(deviceid)) {
    throw new customexception(httpstatus.not_acceptable.value(), "not deviceid in the head of the request");
   }
   string codeparamname = customymlconfig.getlogins().getmobile().getparameter().getcode();
   string code = request.getparameter(codeparamname);
   if (stringutils.isblank(code)) {
    throw new customexception(httpstatus.not_acceptable.value(), "not code in the parameters of the request");
   }
   string key = systemconstant.default_mobile_key_pix + deviceid;
   smscodepo smscodepo = (smscodepo) redistemplate.opsforvalue().get(key);
   if (smscodepo.isexpried()){
    throw new customexception(httpstatus.bad_request.value(), "the verification code has expired");
   }
   string smscode = smscodepo.getcode();
   if (stringutils.isblank(smscode)) {
    throw new customexception(httpstatus.bad_request.value(), "verification code does not exist");
   }
   if (stringutils.equals(code, smscode)) {
    redistemplate.delete(key);
    //let it go
    filterchain.dofilter(request, response);
   } else {
    throw new customexception(httpstatus.bad_request.value(), "validation code is incorrect");
   }
  }else {
   //let it go
   filterchain.dofilter(request, response);
  }
 }
}

注:dofilterinternal()

自定義驗證碼過濾校驗

2.2.2.2.將自定義驗證碼過濾器添加到spring security過濾器鏈

?
1
http.addfilterbefore(validatecodefilter, abstractpreauthenticatedprocessingfilter.class)

注:添加到認證預處理過濾器前

3.測試效果

spring security自定義認證登錄的全過程記錄

spring security自定義認證登錄的全過程記錄

spring security自定義認證登錄的全過程記錄

spring security自定義認證登錄的全過程記錄

最后附上源碼地址:https://gitee.com/catalpaflat/springsecurity.git  

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://juejin.im/post/5a3b7f5c6fb9a0452936ee2a

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 黄www片| 久久精品99久久久久久2456 | 欧美 国产 亚洲 卡通 综合 | 亚洲成人国产综合 | 美女视频网站黄色 | 欧美性激情视频 | 一级电影免费 | 久草在线观看资源 | 手机黄色小视频 | 成人午夜免费国产 | 中文字幕爱爱视频 | 国产视频导航 | 羞羞的视频免费 | 在线观看91精品 | av色哟哟 | 中文字幕偷拍 | 综合国产一区 | 亚洲第九十九页 | 国产黄色录像片 | 国产精品二区高清在线 | 91九色视频| 精品久久久久久久久久久αⅴ | 黄色特级视频 | 国产亚洲欧美日韩在线观看不卡 | 网站一区| 成人免费观看av | 欧美三级短视频 | 成人免费观看av | 最新欧美精品一区二区三区 | 免费一级欧美在线观看视频 | 逼片| 国产成人精品一区在线播放 | 日本一区二区三区高清不卡 | 国产精品一区久久久久 | 免费a视频| 亚洲日韩精品欧美一区二区 | 亚洲第一男人天堂 | 蜜桃网站免费 | 午夜a狂野欧美一区二区 | 模特三级在线观看 | 国产电影精品久久 |