JWT介绍了解
文章目錄
- 跨域&&JWT
- 1. 跨域
- 1.1 跨域解決
- 1.1.1 JSONP跨域
- 1.1.1.1 原生實現:
- 1.1.1.2 jQuery實現:
- 1.1.2 CORS跨域資源共享
- 1.1.2.1 CORS實現
- 1.1.3 兩種區別
- 2. JWT介紹
- 使用jwt
跨域&&JWT
1. 跨域
跨域介紹:
目前的項目一般都是前后端分離的,這時就會造成兩臺服務器去完成對應的功能,因為有了兩臺服務器,所以就會導致ip、端口等的不一致,這時就會造成一個服務器不能訪問另外一個服務器,就會造成跨域問題
產生原因:
現在的瀏覽器的同源策略限制導致的,同源策略/SOP(same origin policy) 是一種約定,是瀏覽器最核心也是最基本的安全功能,如果少了同源策略,則瀏覽器的正常功能都可能會受影響。web安全就是基于同源策略的,瀏覽器只是同源策略的一種實現,假設缺少了,可能遭受 XSS,CSRF 等攻擊。
什么叫不同源:只要協議、主機、端口有一個不一樣就是不同源,瀏覽器上只要不同源ajax就會報錯
1.1 跨域解決
1.1.1 JSONP跨域
1.1.1.1 原生實現:
前端:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>注冊</title> </head> <body> <form action=""><span>賬號</span><input type="text" name="username"><span></span><br><span>密碼</span><input type="password" name="password"><br><input type="submit" value="注冊"> </form> <script src="../js/jquery-3.6.0.js"></script> <script>//使用jsonp完成 注意只能用與get請求//設置回調函數function callBack(data) {var element = document.querySelector("input[name='username'] + span");if (data.code){element.style.color = "green";}else {element.style.color = "red";}element.innerHTML = data.msg;}$("input[name='username']").blur(function () {//用戶名let value = this.value;//獲取一個script標簽var htmlScriptElement = document.createElement("script");//設置script標簽的地址 將參數給傳進去以及要調用的回調函數htmlScriptElement.src = "http:/localhost/ajax/user/selectUsername?username="+ value + "&method=callBack";//將script標簽添加到body里面document.body.appendChild(htmlScriptElement);});</script> </body> </html>后臺主要邏輯代碼(doget 不放上來了):
//檢查用戶名public void selectUsername(HttpServletRequest request,HttpServletResponse response) throws IOException {String username = request.getParameter("username");String method = request.getParameter("method");//response.setContentType("application/json;charset=utf-8");response.setContentType("application/javascript;charset=utf-8");PrintWriter writer = response.getWriter();Result result = new Result();if ("zhangsan".equals(username)){result.setCode(1);result.setMsg("賬號不可用");} else{result.setCode(0);result.setMsg("√");}String s = JSON.toJSONString(result);//response.getWriter().write(s);//返回的數據就是調用這個方法writer.write( method + "("+s+")");}1.1.1.2 jQuery實現:
前端:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>注冊</title> </head> <body> <form action=""><span>賬號</span><input type="text" name="username"><span></span><br><span>密碼</span><input type="password" name="password"><br><input type="submit" value="注冊"> </form> <script src="../js/jquery-3.6.0.js"></script> <script>//使用jq完成 不常用格式$("input[name='username']").blur(function () {//用戶名let value = this.value;$.ajax({url:"http:/localhost/ajax/user/selectUsername",//請求路徑type:"get",//請求方式 默認getdata:{username: value},//請求參數dataType:"jsonp",//響應數據類型headers:{a:"a",b:"b"},//請求頭,是可以傳參數的timeout:5000,//超時時間success:function (result) {//里面的參數可以是很多,//響應200的回調,具體操作let span = $("input[name='username']+span");if (result.code == 0){span.css("color","green");}else {span.css("color","red");}},error:function (){//響應失敗的回調,超時,非200,datatype和響應的數據類型不一致},compile:function () {//無論成功還是失敗都要執行}})});</script> </body> </html>后端:
//檢查用戶名public void selectUsername(HttpServletRequest request,HttpServletResponse response) throws IOException {String username = request.getParameter("username");String method = request.getParameter("callBack");//jquery實現的時候就是callback// String method = request.getParameter("method");//原生實現的時候就是method//response.setContentType("application/json;charset=utf-8");response.setContentType("application/javascript;charset=utf-8");PrintWriter writer = response.getWriter();Result result = new Result();if ("zhangsan".equals(username)){result.setCode(1);result.setMsg("賬號不可用");} else{result.setCode(0);result.setMsg("√");}String s = JSON.toJSONString(result);//response.getWriter().write(s);//返回的數據就是調用這個方法writer.write( method + "("+s+")");}注意:
1.1.2 CORS跨域資源共享
CORS 介紹:
CORS 跨域資源共享,CORS 是一個W3C的標準,全稱是跨域資源共享(CROSS-origin resources sharing)
它允許瀏覽器向跨域的服務器發送一個XMLHttpRequest請求,從而克服了ajax只能同源使用的限制。CORS需要瀏覽器和服務器同時支持才可以。目前主流的瀏覽器都是支持的,除了IE10以下的版本。
瀏覽器將CORS的跨域請求分為簡單請求和非簡單請求
只要滿足如下的兩個條件就是簡單請求
只要不滿足如上的兩個條件都是非簡單請求,瀏覽器針對兩種請求的處理方式是不一樣的
請求頭介紹:
GET /cors HTTP/1.1
Origin: http://localhost
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0…
上面的請求頭中:Origin 表示這個請求從哪個源(協議+主機+端口)來的,服務器根據這個源決定是否同意這個請求。
CORS的響應都是以Access-Control-開頭的
他的值可以是一個*,表示接收任意域名的請求,也可以是具體的值 http://localhost 表示只接受 來自這個地方的請求
他的值是一個boolean類型,如果為true,表示客戶端允許發送cookie,默認情況下Cookie是不會包含在跨域的請求中。也就是如果不想攜帶cookie不設置這個頭即可。
CORS 請求是: XMLHttpRequest 對象的 getResponseHeader 方法默認只能獲取6個響應頭:Cache-Control、Content-language、Content-Type、Expirse、Last-Modified、Pragma 。如果想讓客戶端獲取更多的響應頭就必須在 Access-Control-Expose-Headers 的值中進行指定。然后就可以在getResponseHeader中獲取到。
1.1.2.1 CORS實現
實現CORS 一般只需要在服務器配置一個過濾器即可,因為主流的瀏覽器都是支持的。CORS一般會發送兩次請求過來,第一次發送OPTIONS 請求,獲取對應的響應頭,第二次才會發送執行任務的請求。
過濾器:
package com.xiaowang.filter; /*** @Author:小王吖* @Date:2023/1/14*/import javax.servlet.*; import javax.servlet.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;@WebFilter( "/*") public class CORSFilter implements Filter {public void init(FilterConfig config) throws ServletException {}public void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {HttpServletRequest request1 = (HttpServletRequest) request;HttpServletResponse response1 = (HttpServletResponse) response;//獲取要的方法String method = request1.getMethod();//設置響應頭//設置哪些地方的請求可以跨域 * 表示任意請求 多個值可以用,隔開//"http://localhost:9999,http://localhost:8888"response1.setHeader("Access-Control-Allow-Origin",request1.getHeader("Origin"));//是否允許攜帶cookieresponse1.setHeader("Access-Control-Allow-Credentials","true");// 允許的請求方式response1.setHeader("Access-Control-Allow-Methods","GET,POST,HEAD,OPTIONS");//允許的請求頭response1.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type,Token,Accept, Connection, User-Agent, Cookie");//允許瀏覽器獲取的響應頭response1.setHeader("Access-Control-Expose-Headers","Token");// 超時時間response1.setHeader("Access-Control-Max-Age","362880");if ("OPTIONS".equalsIgnoreCase(request1.getMethod())){return;}chain.doFilter(request1,response1);} }前端(普通的ajax就行了):
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>注冊</title> </head> <body> <form action=""><span>賬號</span><input type="text" name="username"><span></span><br><span>密碼</span><input type="password" name="password"><br><input type="submit" value="注冊"> </form> <script src="../js/jquery-3.6.0.js"></script> <script>//設置回調函數function callBack(data) {var element = document.querySelector("input[name='username'] + span");if (data.code==0){element.style.color = "green";}else {element.style.color = "red";}element.innerHTML = data.msg;}//使用jq完成 不常用格式$("input[name='username']").blur(function () {//用戶名let value = this.value;$.ajax({url:"http://localhost/ajax/user/selectUsername",//請求路徑type:"get",//請求方式 默認getdata:{username: value},//請求參數dataType:"json",//響應數據類型headers:{a:"a",b:"b"},//請求頭,是可以傳參數的timeout:5000,//超時時間success:function (result) {//里面的參數可以是很多,console.log("success");//響應200的回調,具體操作let span = $("input[name='username']+span");if (result.code == 0){span.css("color","green");}else {// span.text(result.msg);span.css("color","red");}span.text(result.msg);},error:function (){console.log("error");//響應失敗的回調,超時,非200,datatype和響應的數據類型不一致},compile:function () {//無論成功還是失敗都要執行}})}); </script> </body> </html>后端(注意使用的是cors所以不需要將其寫成jsonp的形式哦):
//檢查用戶名public void selectUsername(HttpServletRequest request,HttpServletResponse response) throws IOException {String username = request.getParameter("username");//String method = request.getParameter("callBack");//jquery實現的時候就是callbackString method = request.getParameter("method");//原生實現的時候就是methodresponse.setContentType("application/json;charset=utf-8");//response.setContentType("application/javascript;charset=utf-8");PrintWriter writer = response.getWriter();Result result = new Result();if ("zhangsan".equals(username)){result.setCode(1);result.setMsg("賬號不可用");} else{result.setCode(0);result.setMsg("√");}String s = JSON.toJSONString(result);//response.getWriter().write(s);//返回的數據就是調用這個方法writer.write(s);}1.1.3 兩種區別
jsonp只有一次請求,cors是兩次請求(CORS一般會發送兩次請求過來,第一次發送OPTIONS 請求,獲取對應的響應頭,第二次才會發送執行任務的請求。)
2. JWT介紹
JWT介紹:
-
WT的全稱是json web token 。是一種令牌,。是為了在網絡應用環境中傳遞聲明(token令牌)而執行的一種基于json的開發標準(RFC7519).。
-
這個token被設置的緊湊而安全。特別適用于分布式單點登錄(SSO)場景。
-
JWT的聲明一般是在身份提供者和服務器提供者之間傳遞被認證的用戶身份信息。以便于從資源服務器獲取資源。該token可以直接用于被認證和加密。
單點登錄:有很多項目,但是只用登錄一次,相當于,QQ號授權后,可以登錄很多應用。
流程上來看:
JWT結構:
JWT 是由三段信息構成的,將三段信息用 . (點)連接在一次就構成了JWT的字符串:、
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6ImM2OTI3NzAxLTNmNmMtNDA2NS1hOGFiLWNiOWUwMzUzOTViMiIsImlhdCI6MTYxODQ2OTMxMiwiZXhwIjoxNjE4NDcyOTEyfQ.mo3xwud0tH9Tjx2UQUXZohPUBgZhbGsjmG6yUGcrODU
JWT的三段構成:
第一部分:header
jwt的header部分承載了兩部分信息:聲明類型:JWT(如何產生的)加密算法:HS256完整頭部信息如下:{"typ":"JWT","alg":"HS256"}將這一部分頭部信息使用Base64加密后得到eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9base64加密是對稱的,可以通過base64解密
第二部分:Payload(載荷)
載荷就是存放有效信息的地方,這個信息中包含了三部分公有的聲明公有的聲明可以添加任何信息進去,一般添加用戶相關的信息或者業務相關的信息,不建議添加敏感信息,因為這部分用戶可以在客戶端解密私有的聲明是提供者和消費者共同定義的聲明,一般也不建議存放敏感信息,也可以解密的注冊的聲明 (建議但不強制)iss: jwt的簽發者sub: jwt面向的用戶aud: 接收jwt的一方exp: jwt的過期時間,這個時間一定要大于簽發時間iat: jwt的簽發時間nbf: 定義在什么時間之前,jwt是不可用的jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊例:定義一個載荷{"sub":"1234567890","name":"John Doe","admin":true,"jti":"c6927701-3f6c-4065-a8ab-cb9e035395b2","iat":1618469312,"exp":1618472912}使用Base64加密后如下eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6ImM2OTI3NzAxLTNmNmMtNDA2NS1hOGFiLWNiOWUwMzUzOTViMiIsImlhdCI6MTYxODQ2OTMxMiwiZXhwIjoxNjE4NDcyOTEyfQ第三部分:簽證Signing
這部分的信息是由三部分組成 header(加密后的) payload(加密后的) secret將上面的三部分使用.連接成字符串,然后將這個字符串使用header中定義的加密算法進行加鹽加密,得到第三部分加密方式如下: HS256(Base64(header).Base64(payload),secret)最后得到 mo3xwud0tH9Tjx2UQUXZohPUBgZhbGsjmG6yUGcrODU 需要注意的是secret 是保存在服務器的,jwt的生成也是在服務器生成的,所以secret可以看做進行jwt的簽發的鹽值。所以secret算是服務器的私鑰,在任何情況下都不能將私鑰暴露出去。一旦客戶端知道了這個私鑰,那就意味著客戶端可以自我簽發jwt了。使用jwt
添加依賴 :
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt --> <dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.10.3</version> </dependency>總結
- 上一篇: 奶爸英语学习课程要点(第8课, 彻底突破
- 下一篇: java美容美发项目下载_汉之源美容美发