国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

寫了這么多年代碼,這樣的登錄方式還是頭一回見!

開發(fā) 前端
Spring Security 系列還沒搞完,最近還在研究。有的時候我不禁想,如果從 Spring Security 誕生的第一天開始,我們就一直在追蹤它,那么今天再去看它的源碼一定很簡單,因為我們了解到每一行代碼的緣由。

 Spring Security 系列還沒搞完,最近還在研究。

[[332172]]

有的時候我不禁想,如果從 Spring Security 誕生的第一天開始,我們就一直在追蹤它,那么今天再去看它的源碼一定很簡單,因為我們了解到每一行代碼的緣由。

然而事實上我們大部分人都是中途接觸到它的,包括松哥自己。所以在閱讀源碼的時候,有時候會遇到一些不是那么容易理解的東西,并不是說這個有多難,只是我們不了解 N 年前的開發(fā)環(huán)境,因此也就不容易理解某一行代碼出現(xiàn)的意義。

所以為了搞透徹這個框架,有時候我們還得去了解之前發(fā)生了什么。

這就跟學(xué) Spring Boot 一樣,很多小伙伴問要不要跳過 SSM ,我說不要,甚至還專門寫了一篇文章(Spring Boot 要怎么學(xué)?要學(xué)哪些東西?要不要先學(xué) SSM?),跳過了 SSM ,Spring Boot 中的很多東西就無法真正理解。

扯遠了。。。

Spring Security 中對 HttpServletRequest 請求進行了封裝,重寫了 HttpServletRequest 中的幾個和安全管理相關(guān)的方法,想要理解 Spring Security 中的重寫,就要先從 HttpServletRequest 開始看起。

有小伙伴可能會說,HttpServletRequest 能跟安全管理扯上什么關(guān)系?今天松哥就來和大家捋一捋,我們不講 Spring Security,就來單純講講 HttpServletRequest 中的安全管理方法。

1.HttpServletRequest

在 HttpServletRequest 中,我們常用的方法如:

  • public String getHeader(String name);
  • public String getParameter(String name);
  • public ServletInputStream getInputStream()
  • ...

這些常見的方法可能大家都有用過,還有一些不常見的,和安全相關(guān)的方法:

  1. public String getRemoteUser(); 
  2. public boolean isUserInRole(String role); 
  3. public java.security.Principal getUserPrincipal(); 
  4. public boolean authenticate(HttpServletResponse response) 
  5.             throws IOException, ServletException; 
  6. public void login(String username, String password) throws ServletException; 
  7. public void logout() throws ServletException; 

前面三個方法,在之前的 Servlet 中就有,后面三個方法,則是從 Servlet3.0 開始新增加的方法。從方法名上就可以看出,這些都是和認(rèn)證相關(guān)的方法,但是這些方法,我估計很多小伙伴都沒用過,因為不太實用。

在 Spring Security 框架中,對這些方法進行了重寫,進而帶來了一些好玩并且方便的特性,這個松哥在后面的文章中再和大家分享。

要理解 Spring Security 中的封裝,就得先來看看,不用框架,這些方法該怎么用!

2.實踐出真

知我們創(chuàng)建一個普普通通的 Web 項目,不使用任何框架(后面的案例都基于此),然后在 doGet 方法中打印出 HttpServletRequest 的類型,代碼如下:

  1. @Override 
  2. protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException { 
  3.     System.out.println("request.getClass() = " + request.getClass()); 

代碼運行打印結(jié)果如下:

  1. request.getClass() = class org.apache.catalina.connector.RequestFacade 

HttpServletRequest 是一個接口,而 RequestFacade 則是一個正兒八經(jīng)的 class。

HttpServletRequest 是 Servlet 規(guī)范中定義的 ServletRequest,這相當(dāng)于是標(biāo)準(zhǔn)的 Request;但是在 Tomcat 中的 Request 則是 Tomcat 自己自定義的 Request,自定義的 Request 實現(xiàn)了 HttpServletRequest 接口并且還定義了很多自己的方法,這些方法還是 public 的,如果直接使用 Tomcat 自定義的 Request,開發(fā)者只需要向下轉(zhuǎn)型就能調(diào)用這些 Tomcat 內(nèi)部方法,這是有問題的,所以又用 RequestFacade 封裝了一下,以至于我們實際上用到的就是 RequestFacade 對象。

那么毫無疑問,HttpServletRequest#login 方法具體實現(xiàn)就是在 Tomcat 的 Request#login 方法中完成的。經(jīng)過源碼追蹤,我們發(fā)現(xiàn),登錄的數(shù)據(jù)源是由 Tomcat 中的 Realm 提供的,注意這個 Realm 不是 Shiro 中的 Realm。

Tomcat 中提供了 6 種 Realm,可以支持與各種數(shù)據(jù)源的對接:

  • JDBCRealm:很明顯,這個 Realm 可以對接到數(shù)據(jù)庫中的用戶信息。
  • DataSourceRealm:它通過一個 JNDI 命名的 JDBC 數(shù)據(jù)源在關(guān)系型數(shù)據(jù)庫中查找用戶。
  • JNDIRealm:通過一個 JNDI 提供者1在 LDAP 目錄服務(wù)器中查找用戶。
  • UserDatabaseRealm:這個數(shù)據(jù)源在 Tomcat 的配置文件中 conf/tomcat-users.xml。
  • MemoryRealm:這個數(shù)據(jù)源是在內(nèi)存中,內(nèi)存中的數(shù)據(jù)也是從 conf/tomcat-users.xml 配置文件中加載的。
  • JAASRealm:JAAS 架構(gòu)來實現(xiàn)對用戶身份的驗證。

如果這些 Realm 無法滿足需求,當(dāng)然我們也可以自定義 Realm,只不過一般我們不這樣做,為啥?因為這這種登錄方式用的太少了!今天這篇文章純粹是和小伙伴們開開眼界。

如果自定義 Realm 的話,我們只需要實現(xiàn) org.apache.catalina.Realm 接口,然后將編譯好的 jar 放到 $CATALINA_HOME/lib 下即可,具體的配置則和下面介紹的一致。

接下來我和大家介紹兩種配置方式,一個是 UserDatabaseRealm,另一個是 JDBCRealm。

2.1 基于配置文件登錄

我們先來定義一個 LoginServlet:

  1. @WebServlet(urlPatterns = "/login"
  2. public class LoginServlet extends HttpServlet { 
  3.     @Override 
  4.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  5.         doPost(req, resp); 
  6.     } 
  7.  
  8.     @Override 
  9.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  10.         String username = req.getParameter("username"); 
  11.         String password = req.getParameter("password"); 
  12.         try { 
  13.             req.login(username, password); 
  14.         } catch (ServletException e) { 
  15.             req.getRequestDispatcher("/login.jsp").forward(req, resp); 
  16.             return
  17.         } 
  18.         boolean login = req.getUserPrincipal() != null && req.isUserInRole("admin"); 
  19.         if (login) { 
  20.             resp.sendRedirect("/hello"); 
  21.             return
  22.         } else { 
  23.             req.getRequestDispatcher("/login.jsp").forward(req, resp); 
  24.         } 
  25.     } 

當(dāng)請求到達后,先提取出用戶名和密碼,然后調(diào)用 req.login 方法進行登錄,如果登錄失敗,則跳轉(zhuǎn)到登錄頁面。

登錄完成后,通過獲取登錄用戶信息以及判斷登錄用戶角色,來確保用戶是否登錄成功。

如果登錄成功,就跳轉(zhuǎn)到項目應(yīng)用首頁,否則就跳轉(zhuǎn)到登錄頁面。

接下來定義 HelloServlet:

  1. @WebServlet(urlPatterns = "/hello"
  2. public class HelloServlet extends HttpServlet { 
  3.     @Override 
  4.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  5.         doPost(req,resp); 
  6.     } 
  7.  
  8.     @Override 
  9.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  10.         Principal userPrincipal = req.getUserPrincipal(); 
  11.         if (userPrincipal == null) { 
  12.             resp.setStatus(401); 
  13.             resp.getWriter().write("please login"); 
  14.         } else if (!req.isUserInRole("admin")) { 
  15.             resp.setStatus(403); 
  16.             resp.getWriter().write("forbidden"); 
  17.         }else
  18.             resp.getWriter().write("hello"); 
  19.         } 
  20.     } 

在 HelloServlet 中,先判斷用戶是否已經(jīng)登錄,沒登錄的話,就返回 401,已經(jīng)登錄但是不具備相應(yīng)的角色,就返回 403,否則就返回 hello。

接下來再定義 LogoutServlet,執(zhí)行注銷操作:

  1. @WebServlet(urlPatterns = "/logout"
  2. public class LogoutServlet extends HttpServlet { 
  3.     @Override 
  4.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  5.         doPost(req,resp); 
  6.     } 
  7.  
  8.     @Override 
  9.     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  10.         req.logout(); 
  11.         resp.sendRedirect("/hello"); 
  12.     } 

logout 方法也是 HttpServletRequest 自帶的。

最后再簡單定義一個 login.jsp 頁面,如下:

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %> 
  2. <html> 
  3. <head> 
  4.     <title>Title</title> 
  5. </head> 
  6. <body> 
  7. <form action="/login" method="post"
  8.     <input type="text" name="username"
  9.     <input type="text" name="password"
  10.     <input type="submit" value="登錄"
  11. </form> 
  12. </body> 
  13. </html> 

所有工作都準(zhǔn)備好了,接下來就是數(shù)據(jù)源了,默認(rèn)情況下加載的是 conf/tomcat-users.xml 中的數(shù)據(jù),找到 Tomcat 的這個配置文件,修改之后內(nèi)容如下:

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <tomcat-users> 
  3.     <role rolename="admin"/> 
  4.     <user username="javaboy" password="123" roles="admin"/> 
  5. </tomcat-users> 

配置完成后,啟動項目進行測試。登錄用戶名是 javaboy,登錄密碼是 123,具體的測試過程我就不再演示了。

2.2 基于數(shù)據(jù)庫登錄

如果想基于數(shù)據(jù)庫登錄,我們需要先準(zhǔn)備好數(shù)據(jù)庫和表,需要兩張表,user 表和 role 表,如下:

  1. CREATE TABLE `user` ( 
  2.   `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
  3.   `username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
  4.   `passwordvarchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
  5.   PRIMARY KEY (`id`) 
  6. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 
  7. CREATE TABLE `role` ( 
  8.   `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
  9.   `username` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
  10.   `role_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
  11.   PRIMARY KEY (`id`) 
  12. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 

然后向表中添加兩行模擬數(shù)據(jù):

接下來,找到 Tomcat 的 conf/server.xml 文件,修改配置,如下:

  1. <Realm className="org.apache.catalina.realm.LockOutRealm"
  2.   <Realm  className="org.apache.catalina.realm.JDBCRealm" debug="99" 
  3.         driverName="com.mysql.jdbc.Driver" 
  4.         connectionURL="jdbc:mysql://localhost:3306/basiclogin" 
  5.         connectionName="root" connectionPassword="123" 
  6.         userTable="user" userNameCol="username"     
  7.         userCredCol="password" 
  8.         userRoleTable="role" roleNameCol="role_name" /> 
  9. </Realm> 

在這段配置中:

  • 指定 JDBCRealm。
  • 指定數(shù)據(jù)庫驅(qū)動。
  • 指定數(shù)據(jù)庫連接地址。
  • 指定數(shù)據(jù)庫連接用戶名/密碼。
  • 指定用戶表名稱;用戶名的字段名以及密碼字段名。
  • 指定角色表名稱;以及角色字段名。

配置完成后,再次登錄測試,此時的登錄數(shù)據(jù)就是來自數(shù)據(jù)庫的數(shù)據(jù)了。

3.優(yōu)化

前面的 HelloServlet,我們是在代碼中手動配置的,要是每個 Servlet 都這樣配置,這要搞到猴年馬月了~

所以我們對此可以在 web.xml 中進行手動配置。

首先我們創(chuàng)建一個 AdminServlet 進行測試,如下:

  1. @WebServlet(urlPatterns = "/admin/hello"
  2. public class AdminServlet extends HttpServlet { 
  3.     @Override 
  4.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  5.         resp.getWriter().write("hello admin!"); 
  6.     } 

然后在 web.xml 中進行配置:

  1. <security-constraint
  2.     <web-resource-collection> 
  3.         <web-resource-name>admin</web-resource-name
  4.         <url-pattern>/admin/*</url-pattern> 
  5.     </web-resource-collection> 
  6.     <auth-constraint
  7.         <role-name>admin</role-name
  8.     </auth-constraint
  9. </security-constraint
  10. <security-role> 
  11.     <role-name>admin</role-name
  12. </security-role> 

這個配置表示 /admin/* 格式的請求路徑,都需要具有 admin 角色才能訪問,否則就訪問不到,這樣,每一個 Admin 相關(guān)的 Servlet 就被保護起來了,不用在 Servlet 中寫代碼判斷了。

4.小結(jié)

好啦,經(jīng)過本文的介紹,相信小伙伴們對于 HttpServletRequest 中關(guān)于認(rèn)證的幾個方法基本上都了解了,接下來的文章松哥將繼續(xù)和大家介紹這些方法在 Spring Security 框架中是如何進行演化的,看懂了本文,后面的文章就很好理解了~

本文案例下載地址:https://github.com/lenve/javaboy-code-samples

本文轉(zhuǎn)載自微信公眾號「江南一點雨」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系江南一點雨公眾號。

 

責(zé)任編輯:武曉燕 來源: 江南一點雨
相關(guān)推薦

2018-10-06 21:51:37

代碼SOLID編程

2018-10-07 06:30:40

代碼設(shè)計模式面向?qū)ο笤瓌t

2017-11-30 07:30:27

程序員代碼軟件世界觀

2024-02-20 08:09:51

Java 8DateUtilsDate工具類

2025-08-01 00:00:00

2021-02-03 08:24:32

JavaScript技巧經(jīng)驗

2015-03-27 10:20:41

谷歌地圖谷歌偉大

2021-09-13 10:03:54

藍牙連接藍牙藍牙設(shè)備

2020-07-28 15:18:52

Gartner信息安全網(wǎng)絡(luò)安全

2020-03-30 16:18:02

代碼開發(fā)工具

2023-11-13 08:49:54

2022-04-21 07:52:08

JS線程GUI渲染

2024-03-01 17:01:15

GraphQL后端

2020-07-21 18:37:14

代碼條件變量

2023-05-31 16:40:01

2020-11-20 10:22:34

代碼規(guī)范設(shè)計

2017-08-21 15:10:30

筆記本塑料材質(zhì)工藝

2021-04-27 15:13:20

Java開發(fā)語言

2021-12-16 10:16:18

硬盤WindowsiPhone

2024-05-23 10:34:15

CSS 3CSS技術(shù)
點贊
收藏

51CTO技術(shù)棧公眾號

欧美日韩一级视频| 午夜精品视频| 日日摸天天爽天天爽视频| 亚洲精品国产免费| 国模大尺度一区二区三区| 黑人巨大亚洲一区二区久| 伊人天天久久大香线蕉av色| 91精品国产综合久久久蜜臀图片| 日韩欧美国产综合| 成人精品小蝌蚪| www.18av.com| 中日韩美女免费视频网址在线观看| 美女视频网站黄色亚洲| 91美女精品| 国产成人在线小视频| 久久影院中文字幕| 国产精品久久国产精麻豆99网站 | 成人免费视频网| 色呦呦一区二区三区| 99伊人成综合| 手机在线观看av| 中文字幕无码精品亚洲35| 欧美激情一区二区三区成人| 亚洲色图制服诱惑| 欧美特黄视频| 国产精品yjizz视频网| 国产成人无码一二三区视频| 日本一欧美一欧美一亚洲视频 | 日韩大片在线| 成人一区二区不卡免费| 亚洲欧美日韩另类精品一区二区三区| 一本一本久久a久久精品牛牛影视 一本色道久久综合亚洲精品小说 一本色道久久综合狠狠躁篇怎么玩 | 1769免费视频在线观看| 亚洲精品偷拍视频| 欧美激情aaaa| 色偷偷一区二区三区| 麻豆国产欧美日韩综合精品二区| 精品一区二区三区中文字幕| 国产超碰精品在线观看 | 欧洲成人av| 一区二区不卡在线视频 午夜欧美不卡' | 亚洲国产欧美精品| 国产人久久人人人人爽| 亚洲激情中文| 国产高清不卡| 4虎在线播放1区| 国产一区二区三区四区五区在线| 亚洲欧美日韩中文视频| 国模视频一区| 国内不卡的一区二区三区中文字幕| 亚洲伦理网站| 国模精品视频| 国产xxxxx在线观看| 91精品啪aⅴ在线观看国产| 亚洲国产成人av在线| 亚洲日韩欧美一区二区在线| 美女91精品| 欧美午夜寂寞| 欧亚在线中文字幕免费| av在线不卡播放| 成人免费a级片| 99精彩视频在线观看免费| 国产亚洲欧洲高清| 欧美小视频在线| 91麻豆国产自产在线观看| 在线成人亚洲| 精品少妇一区| 黄色视屏免费在线观看| www.99re.av| 亚洲高清在线观看一区| 国产精品久久久久久久久久久久久| 亚洲国产精品一区二区三区| 亚洲18女电影在线观看| 99久久er热在这里只有精品66| 欧美日韩影院| 电影一区二区在线观看| aa视频在线观看| 亚洲最新合集| 冲田杏梨av在线| 在线成人av电影| 国产欧美一区二区三区四区| 久久精品中文字幕一区| 欧美女孩性生活视频| 亚洲欧洲美洲综合色网| 九一九一国产精品| 欧美国产美女| 97青娱国产盛宴精品视频| 91美女主播在线视频| 黄色av网站在线| 九色丨porny丨自拍入口| 欧美性猛交内射兽交老熟妇| 国产精品久久久久久久久婷婷 | www.久久99| 制服丝袜在线播放| 青娱在线视频| 五月婷婷狠狠操| 精品人妻人人做人人爽| 日韩激情视频| 国产精品午夜av在线| 国产精品福利在线观看| 久久久精品在线观看| 日韩国产高清视频在线| 欧美日韩在线播放| 欧美日韩免费在线观看| 亚洲三级免费观看| 久久久亚洲午夜电影| 激情欧美日韩一区二区| 久久国产精品亚洲77777| 中文视频一区| 日韩电影二区| 精品国产一区二区三区小蝌蚪| 91国内精品| 91国产一区| 国产成人精品一区二区三区免费| 岛国在线视频网站| 欧美草逼视频| 日韩另类在线| 欧洲精品二区| 伊人福利在线| 人人澡人人添人人爽一区二区| 91最新在线| 岛国大片在线观看| 成人高清免费在线播放| 成年人在线看| 在线视频1区2区| 9色在线观看| 97超碰国产一区二区三区| 麻豆av电影在线观看| 中文字幕在线永久在线视频 | 91久久夜色精品国产网站| 4438全国成人免费| 欧美精品久久久久久久免费观看 | 婷婷综合视频| 99久久99视频只有精品| 日韩理论电影| 欧美国产一级| 国产精品99久久精品| 99re久久最新地址获取| 久久久久久影院| 亚洲性感美女99在线| 国产精品综合| 蜜臀久久久99精品久久久久久| 老牛影视一区二区三区| 久久国产日韩欧美精品| 精品一区二区三区影院在线午夜| 国产在线看一区| 99精品欧美一区二区三区小说| 国产日韩精品一区二区三区在线| 国产精品麻豆一区二区| 亚洲午夜一区二区| 一本色道a无线码一区v| 欧美日韩国产中文| 欧美成人一区二区三区在线观看| 亚洲精品一区二区三区精华液| 日韩精品免费在线观看| 国产亚洲激情在线| 欧美国产亚洲精品久久久8v| 清纯唯美亚洲激情| 91在线在线观看| 欧洲亚洲一区| 青草青青在线视频| 天天操,天天操| 在线午夜视频| 黄色网在线看| 欧美日韩尤物久久| 免费看久久久| 欧美99在线视频观看| 国产亚洲一区二区手机在线观看 | 亚洲欧美激情一区| 丰满少妇在线观看| 欧美人与禽猛交乱配视频| 亚洲国产成人精品电影| 韩国中文字幕av| 99久久精品免费观看| 欧美一区二区三区喷汁尤物| 婷婷综合另类小说色区| 欧美精品视频www在线观看| 亚洲黄色片网站| 欧美成年人视频网站欧美| 岛国精品在线播放| 五月天激情图片| 国产一区二区毛片| 久久精品国产综合精品| 秋霞一区二区三区| 亚洲高清不卡av| 在线观看av每日更新免费| 国产精品 欧美精品| 99久久99| 久久视频在线观看| 一本色道久久88精品综合| 伊人久久99| 免费看啪啪网站| 亚洲无吗一区二区三区| 免费在线黄色电影| 周于希免费高清在线观看| 亚洲高清极品| 日韩黄色免费网站| 亚洲人成网站精品片在线观看| 欧美男人的天堂一二区| 九九九热精品免费视频观看网站|