国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

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

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

服務器之家 - 編程語言 - Java教程 - spring boot+jwt實現api的token認證詳解

spring boot+jwt實現api的token認證詳解

2021-06-22 13:26神牛003 Java教程

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

前言

本篇和大家分享jwt(json web token)的使用,她主要用來生成接口訪問的token和驗證,其單獨結合springboot來開發api接口token驗證很是方便,由于jwt的token中存儲有用戶的信息并且有加密,所以適用于分布式,這樣直接吧信息存儲在用戶本地減速了服務端存儲sessiion或token的壓力;

如下快速使用:

?
1
2
3
4
5
6
7
8
9
10
11
12
<!--jwt-->
<dependency>
 <groupid>io.jsonwebtoken</groupid>
 <artifactid>jjwt</artifactid>
 <version>0.9.0</version>
</dependency>
<!--阿里 fastjson依賴-->
<dependency>
 <groupid>com.alibaba</groupid>
 <artifactid>fastjson</artifactid>
 <version>1.2.44</version>
</dependency>

一般使用jwt來達到3種結果:

  • 生成token
  • 驗證token是否有效
  • 獲取token中jwt信息(主要用戶信息)

生成token

引入了jjwt依賴后,要生成token很方便;對于一個token來說,代表的是唯一并且不可逆的,因此我們在生成時需要增加一些唯一數據進去,比如下面的id:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
long currenttime = system.currenttimemillis();
return jwts.builder()
  .setid(uuid.randomuuid().tostring())
  .setissuedat(new date(currenttime)) //簽發時間
  .setsubject("system") //說明
  .setissuer("shenniu003") //簽發者信息
  .setaudience("custom") //接收用戶
  .compresswith(compressioncodecs.gzip) //數據壓縮方式
 
  .signwith(signaturealgorithm.hs256, encrykey) //加密方式
  .setexpiration(new date(currenttime + secondtimeout * 1000)) //過期時間戳
  .addclaims(claimmaps) //cla信息
  .compact();

通過uuid來標記唯一id信息;當然在對token加密時需要用到秘鑰,jwt很是方便她支持了很多中加密方式如:hs256,hs265,md5等復雜及常用的加密方式;

jwt生成的token中內容分為3個部分:head信息,payload信息,sign信息,通常我們要做的是往payload增加一些用戶信息(比如:賬號,昵稱,權限等,但不包含密碼);在對jwt的token有一定了解后,我們來看下真實生成的token值:

?
1
eyjhbgcioijiuzi1niisinppcci6ikdasvaifq.h4siaaaaaaaaafwmtq7cibse7_lwkpdzaesp4qnyinciptx4ine0vbtg4sllfppn7hatgwbwg1bkl4grcbeciwpujzf8iiepjxfapaag2reypuecr2vxyed13nb0pplw3hp1eenblqsquiffy0ohurl3i70evweu_afsejzhd7dlcdv5ntmyhuilhtd3rf_hacchrtv--7yaaaa.i4xwoqtawi0-dwhwn8uz4dbm-vfli5bavyu9lryxu5e

驗證token是否有效

token生成的時都會伴隨者有一個失效的時間,在這我們可以通過setexpiration函數設置過期時間,記住jwt的有效時間不是滑動的,也就是說不做任何處理時,當到達第一次設置的失效時間時,就基本沒用了,要獲取token是否過期可以使用如下方式:

?
1
2
3
4
5
6
7
8
9
public static boolean isexpiration(string token, string encrykey) {
 try {
  return getclaimsbody(token, encrykey)
    .getexpiration()
    .before(new date());
 } catch (expiredjwtexception ex) {
  return true;
 }
}

這里使用了date的before來用獲取的過期時間和當前時間對比,判斷是否繼續有效,需要注意的是如果在token失效后再通過getclaimsbody(token, encrykey)獲取信息,此時會報expiredjwtexception錯誤,我們即可認為過期。

獲取token中jwt信息(主要用戶信息)

通常我們要把登錄用戶信息存儲在jwt生成的token中,這里可以通過 addclaims(claimmaps) 傳遞map來設置信息,反過來要獲取token中的用戶信息,我們需要這樣做:

?
1
2
3
4
return jwts.parser()
  .setsigningkey(encrykey)
  .parseclaimsjws(token)
  .getbody();

此時body獲取出來是claims類型,我們需要從中獲取到用戶信息,需要注意的是在addclaims存儲信息的時候如果存儲的map值沒做過出來,那完整的實體對象存儲進去后會映射成一個linkhasmap類型,如下:

spring boot+jwt實現api的token認證詳解

因此通常會在存儲的時候json化,如下代碼:

?
1
2
3
claimmaps.foreach((key, val) -> {
 claimmaps.put(key, json.tojsonstring(val));
});

再來就是通過get方法獲取我們存儲進去的信息,并json反序列化:

?
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
/**
* 獲取body某個值
*
* @param token
* @param encrykey
* @param key
* @return
*/
public static object getval(string token, string encrykey, string key) {
 return getjws(token, encrykey).getbody().get(key);
}
 
/**
 * 獲取body某個值,json字符轉實體
 *
 * @param token
 * @param encrykey
 * @param key
 * @param tclass
 * @param <t>
 * @return
 */
public static <t> t getvalbyt(string token, string encrykey, string key, class<t> tclass) {
 try {
  string strjson = getval(token, encrykey, key).tostring();
  return json.parseobject(strjson, tclass);
 } catch (exception ex) {
  return null;
 }
}

來到這里一個jwt的util代碼基本就完成了,下面給出完整的代碼例子,僅供參考:

?
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
public class jwtutil {
 
 /**
  * 獲取token - json化 map信息
  *
  * @param claimmaps
  * @param encrykey
  * @param secondtimeout
  * @return
  */
 public static string gettokenbyjson(map<string, object> claimmaps, string encrykey, int secondtimeout) {
  return gettoken(claimmaps, true, encrykey, secondtimeout);
 }
 
 /**
  * 獲取token
  *
  * @param claimmaps
  * @param isjsonmpas
  * @param encrykey
  * @param secondtimeout
  * @return
  */
 public static string gettoken(map<string, object> claimmaps, boolean isjsonmpas, string encrykey, int secondtimeout) {
 
  if (isjsonmpas) {
   claimmaps.foreach((key, val) -> {
    claimmaps.put(key, json.tojsonstring(val));
   });
  }
  long currenttime = system.currenttimemillis();
  return jwts.builder()
    .setid(uuid.randomuuid().tostring())
    .setissuedat(new date(currenttime)) //簽發時間
    .setsubject("system") //說明
    .setissuer("shenniu003") //簽發者信息
    .setaudience("custom") //接收用戶
    .compresswith(compressioncodecs.gzip) //數據壓縮方式
 
    .signwith(signaturealgorithm.hs256, encrykey) //加密方式
    .setexpiration(new date(currenttime + secondtimeout * 1000)) //過期時間戳
    .addclaims(claimmaps) //cla信息
    .compact();
 }
 
 /**
  * 獲取token中的claims信息
  *
  * @param token
  * @param encrykey
  * @return
  */
 private static jws<claims> getjws(string token, string encrykey) {
  return jwts.parser()
    .setsigningkey(encrykey)
    .parseclaimsjws(token);
 }
 
 public static string getsignature(string token, string encrykey) {
  try {
   return getjws(token, encrykey).getsignature();
  } catch (exception ex) {
   return "";
  }
 }
 
 /**
  * 獲取token中head信息
  *
  * @param token
  * @param encrykey
  * @return
  */
 public static jwsheader getheader(string token, string encrykey) {
  try {
   return getjws(token, encrykey).getheader();
  } catch (exception ex) {
   return null;
  }
 }
 
 /**
  * 獲取payload body信息
  *
  * @param token
  * @param encrykey
  * @return
  */
 public static claims getclaimsbody(string token, string encrykey) {
  return getjws(token, encrykey).getbody();
 }
 
 /**
  * 獲取body某個值
  *
  * @param token
  * @param encrykey
  * @param key
  * @return
  */
 public static object getval(string token, string encrykey, string key) {
  return getjws(token, encrykey).getbody().get(key);
 }
 
 /**
  * 獲取body某個值,json字符轉實體
  *
  * @param token
  * @param encrykey
  * @param key
  * @param tclass
  * @param <t>
  * @return
  */
 public static <t> t getvalbyt(string token, string encrykey, string key, class<t> tclass) {
  try {
   string strjson = getval(token, encrykey, key).tostring();
   return json.parseobject(strjson, tclass);
  } catch (exception ex) {
   return null;
  }
 }
 
 /**
  * 是否過期
  *
  * @param token
  * @param encrykey
  * @return
  */
 public static boolean isexpiration(string token, string encrykey) {
  try {
   return getclaimsbody(token, encrykey)
     .getexpiration()
     .before(new date());
  } catch (expiredjwtexception ex) {
   return true;
  }
 }
 
 public static string getsubject(string token, string encrykey) {
  try {
   return getclaimsbody(token, encrykey).getsubject();
  } catch (exception ex) {
   return "";
  }
 }
}

過濾器驗證token

有了基本的jwtutil工具,我們需要用到springboot項目中,一般來說對于登錄授權token驗證可以通過過濾器來操作,這里創建一個authenfilter,用于對post請求過來的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
public class authenfilter implements filter {
 @override
 public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception {
 
  httpservletrequest rq = (httpservletrequest) servletrequest;
  httpservletresponse rp = (httpservletresponse) servletresponse;
  rpbase rpbase = new rpbase();
  try {
   //只接受post
   if (!rq.getmethod().equalsignorecase("post")) {
    filterchain.dofilter(servletrequest, servletresponse);
    return;
   }
 
   string token = rq.getheader("token");
   if (stringutils.isempty(token)) {
    rpbase.setmsg("無token");
    return;
   }
 
   //jwt驗證
   mouser mouser = jwtutil.getvalbyt(token, webconfig.token_encrykey, webconfig.login_user, mouser.class);
   if (mouser == null) {
    rpbase.setmsg("token已失效");
    return;
   }
 
   system.out.println("token用戶:" + mouser.getnickname());
 
   filterchain.dofilter(servletrequest, servletresponse);
  } catch (exception ex) {
  } finally {
   if (!stringutils.isempty(rpbase.getmsg())) {
    rp.setcharacterencoding("utf-8");
    rpbase.setcode(httpstatus.bad_request.value());
    rp.getwriter().write(json.tojsonstring(rpbase));
   }
  }
 }
}

要是自定義過濾器authenfilter生效,還需要把她注冊到容器中,這里通過編碼方式,當然還可以通過@webfilter注解來加入到容器中:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@configuration
public class webfilterconfig {
 
 @bean
 public filterregistrationbean setfilter() {
 
  filterregistrationbean registrationbean = new filterregistrationbean();
  registrationbean.setfilter(new authenfilter());
  registrationbean.addurlpatterns("/api/*");
  registrationbean.setorder(filterregistrationbean.lowest_precedence);
 
  return registrationbean;
 }
}

注意addurlpatterns匹配的是過濾器作用的url連接,根據需求而定;為了驗證效果,這里我創建了兩個接口gettoken和t0,分別是獲取token和post查詢接口,代碼如是:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@restcontroller
public class testcontroller {
 
 @postmapping("/api/t0")
 public string t0() throws myexception {
 
  return uuid.randomuuid().tostring();
 }
 
 @getmapping("/token/{username}")
 public string gettoken(@pathvariable string username) {
 
  mouser mouser = new mouser();
  mouser.setusername(username);
  mouser.setnickname(username);
 
  map<string, object> map = new hashmap<>();
  map.put(webconfig.login_user, mouser);
 
  return jwtutil.gettokenbyjson(map,
    webconfig.token_encrykey,
    webconfig.token_secondtimeout);
 }
}

最終要獲通過head傳遞token值來訪問t01接口,得到如下結果:

spring boot+jwt實現api的token認證詳解

token在有效時間后訪問直接失敗,從新獲取token并訪問t01接口,得到成功的信息:

spring boot+jwt實現api的token認證詳解

git地址: https://github.com/shenniubuxing3

總結

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

原文鏈接:https://www.cnblogs.com/wangrudong003/p/10122706.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 婷婷久久综合 | 日韩电影免费观看 | 久久精品电影 | 国产情侣av自拍 | 国产欧美精品区一区二区三区 | 中文字幕日本一区二区 | 在线观看国产中文字幕 | 欧美日韩成人在线观看 | 亚洲国产欧美一区二区三区丁香婷 | 国产玖玖视频 | 亚洲视频在线视频 | 黄色一级片一级片 | 国产一区二区三区视频在线观看 | 亚洲国产精品视频一区二区三区 | 黄色片在线免费观看 | 福利视频三区 | 久久精品国产免费 | 天天摸天天干 | 中文日韩av | 国产人成精品一区二区三 | 在线欧美亚洲 | 国产a√ | 色毛片| 91亚洲国产 | 亚洲欧美激情视频 | 久久久成人精品 | 亚洲精品一区二区三区在线播放 | 中文字幕一区二区三区乱码在线 | 成人免费观看49www在线观看 | 精品视频网站 | 久久精品国产99 | 91免费视频 | 成人看的免费视频 | 精品日韩一区二区 | 亚洲国产二区 | 国产情侣av自拍 | 欧美国产日韩在线 | 中文字幕日产乱码六区小草 | 日韩免费在线视频 | 色99在线| 亚洲精品免费在线观看视频 |