最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring boot+jwt實(shí)現(xiàn)api的token認(rèn)證詳解

 更新時(shí)間:2018年12月16日 10:34:26   作者:神牛003  
這篇文章主要給大家介紹了關(guān)于spring boot+jwt實(shí)現(xiàn)api的token認(rèn)證的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一學(xué)習(xí)學(xué)習(xí)吧

前言

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

如下快速使用:

<!--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來(lái)達(dá)到3種結(jié)果:

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

生成token

引入了jjwt依賴后,要生成token很方便;對(duì)于一個(gè)token來(lái)說(shuō),代表的是唯一并且不可逆的,因此我們?cè)谏蓵r(shí)需要增加一些唯一數(shù)據(jù)進(jìn)去,比如下面的id:

long currentTime = System.currentTimeMillis();
return Jwts.builder()
  .setId(UUID.randomUUID().toString())
  .setIssuedAt(new Date(currentTime)) //簽發(fā)時(shí)間
  .setSubject("system") //說(shuō)明
  .setIssuer("shenniu003") //簽發(fā)者信息
  .setAudience("custom") //接收用戶
  .compressWith(CompressionCodecs.GZIP) //數(shù)據(jù)壓縮方式

  .signWith(SignatureAlgorithm.HS256, encryKey) //加密方式
  .setExpiration(new Date(currentTime + secondTimeOut * 1000)) //過(guò)期時(shí)間戳
  .addClaims(claimMaps) //cla信息
  .compact();

通過(guò)uuid來(lái)標(biāo)記唯一id信息;當(dāng)然在對(duì)token加密時(shí)需要用到秘鑰,jwt很是方便她支持了很多中加密方式如:HS256,HS265,Md5等復(fù)雜及常用的加密方式;

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

eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAAFWMTQ7CIBSE7_LWkPDzaEsP4QnYINCIptX4INE0vbtg4sLlfPPN7HAtGWbwg1BKL4GrcbEcIwpujZF8iiEpjXFapAAG2ReYpUEcR2VxYED13Nb0ppLW3hP1eEnblqsQuiFfY0OhUrl3I70evweU_aFSejZhd7DlcDv5NTmYHUilHTD3rf_hAccHRTv--7YAAAA.i4xwoQtaWI0-dwHWN8uZ4DBm-vfli5bavYU9lRYxU5E

驗(yàn)證token是否有效

token生成的時(shí)都會(huì)伴隨者有一個(gè)失效的時(shí)間,在這我們可以通過(guò)setExpiration函數(shù)設(shè)置過(guò)期時(shí)間,記住jwt的有效時(shí)間不是滑動(dòng)的,也就是說(shuō)不做任何處理時(shí),當(dāng)?shù)竭_(dá)第一次設(shè)置的失效時(shí)間時(shí),就基本沒(méi)用了,要獲取token是否過(guò)期可以使用如下方式:

public static boolean isExpiration(String token, String encryKey) {
 try {
  return getClaimsBody(token, encryKey)
    .getExpiration()
    .before(new Date());
 } catch (ExpiredJwtException ex) {
  return true;
 }
}

這里使用了date的before來(lái)用獲取的過(guò)期時(shí)間和當(dāng)前時(shí)間對(duì)比,判斷是否繼續(xù)有效,需要注意的是如果在token失效后再通過(guò)getClaimsBody(token, encryKey)獲取信息,此時(shí)會(huì)報(bào)ExpiredJwtException錯(cuò)誤,我們即可認(rèn)為過(guò)期。

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

通常我們要把登錄用戶信息存儲(chǔ)在jwt生成的token中,這里可以通過(guò) addClaims(claimMaps) 傳遞map來(lái)設(shè)置信息,反過(guò)來(lái)要獲取token中的用戶信息,我們需要這樣做:

 return Jwts.parser()
   .setSigningKey(encryKey)
   .parseClaimsJws(token)
   .getBody();

此時(shí)body獲取出來(lái)是Claims類型,我們需要從中獲取到用戶信息,需要注意的是在addClaims存儲(chǔ)信息的時(shí)候如果存儲(chǔ)的map值沒(méi)做過(guò)出來(lái),那完整的實(shí)體對(duì)象存儲(chǔ)進(jìn)去后會(huì)映射成一個(gè)LinkHasMap類型,如下:

因此通常會(huì)在存儲(chǔ)的時(shí)候json化,如下代碼:

 claimMaps.forEach((key, val) -> {
  claimMaps.put(key, JSON.toJSONString(val));
 });

再來(lái)就是通過(guò)get方法獲取我們存儲(chǔ)進(jìn)去的信息,并json反序列化:

/**
* 獲取body某個(gè)值
*
* @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某個(gè)值,json字符轉(zhuǎn)實(shí)體
 *
 * @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;
 }
}

來(lái)到這里一個(gè)Jwt的Util代碼基本就完成了,下面給出完整的代碼例子,僅供參考:

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)) //簽發(fā)時(shí)間
    .setSubject("system") //說(shuō)明
    .setIssuer("shenniu003") //簽發(fā)者信息
    .setAudience("custom") //接收用戶
    .compressWith(CompressionCodecs.GZIP) //數(shù)據(jù)壓縮方式

    .signWith(SignatureAlgorithm.HS256, encryKey) //加密方式
    .setExpiration(new Date(currentTime + secondTimeOut * 1000)) //過(guò)期時(shí)間戳
    .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某個(gè)值
  *
  * @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某個(gè)值,json字符轉(zhuǎn)實(shí)體
  *
  * @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;
  }
 }

 /**
  * 是否過(guò)期
  *
  * @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 "";
  }
 }
}

過(guò)濾器驗(yàn)證token

有了基本的JwtUtil工具,我們需要用到springboot項(xiàng)目中,一般來(lái)說(shuō)對(duì)于登錄授權(quán)token驗(yàn)證可以通過(guò)過(guò)濾器來(lái)操作,這里創(chuàng)建一個(gè)AuthenFilter,用于對(duì)post請(qǐng)求過(guò)來(lái)的token做驗(yàn)證:

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("無(wú)token");
    return;
   }

   //jwt驗(yàn)證
   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));
   }
  }
 }
}

要是自定義過(guò)濾器AuthenFilter生效,還需要把她注冊(cè)到容器中,這里通過(guò)編碼方式,當(dāng)然還可以通過(guò)@WebFilter注解來(lái)加入到容器中:

@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匹配的是過(guò)濾器作用的url連接,根據(jù)需求而定;為了驗(yàn)證效果,這里我創(chuàng)建了兩個(gè)接口getToken和t0,分別是獲取token和post查詢接口,代碼如是:

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

最終要獲通過(guò)head傳遞token值來(lái)訪問(wèn)t01接口,得到如下結(jié)果:

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

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

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • SpringCloud斷路器Hystrix原理及用法解析

    SpringCloud斷路器Hystrix原理及用法解析

    這篇文章主要介紹了SpringCloud斷路器Hystrix原理及用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • springAI結(jié)合ollama簡(jiǎn)單實(shí)現(xiàn)小結(jié)

    springAI結(jié)合ollama簡(jiǎn)單實(shí)現(xiàn)小結(jié)

    本文主要介紹了springAI結(jié)合ollama簡(jiǎn)單實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • 如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能

    如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能

    人工智能時(shí)代的到來(lái),相信大家已耳濡目染,虹軟免費(fèi),離線開(kāi)放的人臉識(shí)別SDK,正推動(dòng)著全行業(yè)進(jìn)入刷臉時(shí)代,下面這篇文章主要給大家介紹了關(guān)于如何基于SpringBoot實(shí)現(xiàn)人臉識(shí)別功能的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • Nacos集群搭建過(guò)程詳解

    Nacos集群搭建過(guò)程詳解

    這篇文章主要為大家介紹了Nacos集群搭建過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • SpringBoot項(xiàng)目中如何動(dòng)態(tài)切換數(shù)據(jù)源、數(shù)據(jù)庫(kù)

    SpringBoot項(xiàng)目中如何動(dòng)態(tài)切換數(shù)據(jù)源、數(shù)據(jù)庫(kù)

    本文主要介紹了SpringBoot項(xiàng)目中如何動(dòng)態(tài)切換數(shù)據(jù)源、數(shù)據(jù)庫(kù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • Java實(shí)體類實(shí)現(xiàn)鏈?zhǔn)讲僮鲗?shí)例解析

    Java實(shí)體類實(shí)現(xiàn)鏈?zhǔn)讲僮鲗?shí)例解析

    這篇文章主要介紹了Java實(shí)體類實(shí)現(xiàn)鏈?zhǔn)讲僮鲗?shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動(dòng)scheduleUpdate定時(shí)任務(wù)的流程分析

    Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動(dòng)scheduleUpdate定時(shí)任務(wù)的流程分析

    這篇文章主要介紹了Nacos服務(wù)發(fā)現(xiàn)并發(fā)啟動(dòng)scheduleUpdate定時(shí)任務(wù),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • netty中pipeline異常事件分析

    netty中pipeline異常事件分析

    這篇文章主要為大家介紹了netty中pipeline異常事件分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • java 判斷字符串中是否有重復(fù)字符的示例

    java 判斷字符串中是否有重復(fù)字符的示例

    今天小編就為大家分享一篇java 判斷字符串中是否有重復(fù)字符的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • 詳解Java中的Lambda表達(dá)式

    詳解Java中的Lambda表達(dá)式

    Lambda表達(dá)式是Java SE 8中一個(gè)重要的新特性。這篇文章主要介紹了Java中的Lambda表達(dá)式 ,需要的朋友可以參考下
    2019-04-04

最新評(píng)論

阜平县| 油尖旺区| 监利县| 蓝山县| 五指山市| 民和| 开江县| 华蓥市| 岗巴县| 秭归县| 托克托县| 三门县| 闻喜县| 两当县| 杭锦旗| 肃北| 资阳市| 奇台县| 贡山| 伊吾县| 淮北市| 海盐县| 铅山县| 永济市| 佛冈县| 大化| 涞水县| 长顺县| 榆树市| 旬邑县| 台前县| 翁源县| 云林县| 神农架林区| 陈巴尔虎旗| 佛学| 松滋市| 昌江| 朝阳市| 双柏县| 宁津县|