restfull加簽_SpringBoot RestFull API簽名

一、需求如下

對指定的API路徑進行簽名認證,對于沒有指定的無需認證,認證具體到方法。

二、查閱資料與開發

1.了解JWT,實際上用的開源jjwt

2.編寫自定義注解

3.編寫攔截器,主要是攔截特定的url進行簽名驗證,這里解析請求的handler是否有包含自定義注解

確定思路后,開始編寫代碼

A、寫工具,我在網上找的,代碼不復雜,一看就懂,代碼如下/**

* @Title: TokenUtils.java

* @Description:

* @Copyright: Copyright (c) 2018

* @Company:http://www.sinocon.cn

* @author Administrator

* @date 2018年8月21日

* @version 1.0

*/

package cn.sinocon.hive.utils;

import java.security.Key;

import java.util.Date;

import javax.crypto.spec.SecretKeySpec;

import javax.xml.bind.DatatypeConverter;

import cn.hutool.core.date.DateUtil;

import io.jsonwebtoken.Claims;

import io.jsonwebtoken.JwtBuilder;

import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

/**

* @Title: TokenUtils

* @Description:

* @author:Administrator

* @date 2018年8月21日

*/

public class TokenUtils {

/**

* 簽名秘鑰

*/

public static final String SECRET = "LHqDYnwpy7jzhmWdIy7EW3ER64mNlAGKRZWLKFvSKIyWWX";

/**

* 生成token

*

* @param id

* 一般傳入userName

* @return

*/

public static String createJwtToken(String id) {

String issuer = "www.zuidaima.com";

String subject = "8vfu3wqEidZve2";

long ttlMillis = System.currentTimeMillis();

return createJwtToken(id, issuer, subject, ttlMillis);

}

/**

* 生成Token

*

* @param id

* 編號

* @param issuer

* 該JWT的簽發者,是否使用是可選的

* @param subject

* 該JWT所面向的用戶,是否使用是可選的;

* @param ttlMillis

* 簽發時間

* @return token String

*/

public static String createJwtToken(String id, String issuer, String subject, long ttlMillis) {

// 簽名算法 ,將對token進行簽名

SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

// 生成簽發時間

long nowMillis = System.currentTimeMillis();

Date now = new Date(nowMillis);

// 通過秘鑰簽名JWT

byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);

Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

// Let's set the JWT Claims

JwtBuilder builder = Jwts.builder().setId(id).setIssuedAt(now).setSubject(subject).setIssuer(issuer)

.signWith(signatureAlgorithm, signingKey);

// if it has been specified, let's add the expiration

if (ttlMillis >= 0) {

long expMillis = nowMillis + ttlMillis;

Date exp = new Date(expMillis);

builder.setExpiration(exp);

}

// Builds the JWT and serializes it to a compact, URL-safe string

return builder.compact();

}

// Sample method to validate and read the JWT

public static Claims parseJWT(String jwt) {

// This line will throw an exception if it is not a signed JWS (as

// expected)

Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(SECRET)).parseClaimsJws(jwt)

.getBody();

return claims;

}

public static void main(String[] args) {

System.out.println(TokenUtils.createJwtToken("page=10"));

}

}

B、編寫注解/**

* @Title: RequireSignature.java

* @Description:

* @Copyright: Copyright (c) 2018

* @Company:http://www.sinocon.cn

* @author Administrator

* @date 2018年8月18日

* @version 1.0

*/

package cn.sinocon.hive.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

* @Title: RequireSignature

* @Description:

* @author:Administrator

* @date 2018年8月18日

*/

@Target({ElementType.METHOD})// 可用在方法名上

@Retention(RetentionPolicy.RUNTIME)// 運行時有效

public @interface RequireSignature {

}

C。編寫攔截器/**

* @Title: LoginInterceptor.java

* @Description:

* @Copyright: Copyright (c) 2018

* @Company:http://www.sinocon.cn

* @author Administrator

* @date 2018年8月18日

* @version 1.0

*/

package cn.sinocon.hive.interceptor;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import org.springframework.stereotype.Component;

import org.springframework.util.ObjectUtils;

import org.springframework.web.method.HandlerMethod;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import cn.hutool.core.date.DateUtil;

import cn.hutool.core.util.ObjectUtil;

import cn.sinocon.hive.annotation.RequireSignature;

import cn.sinocon.hive.utils.TokenUtils;

import io.jsonwebtoken.Claims;

/**

* @Title: LoginInterceptor

* @Description:

* @author:Administrator

* @date 2018年8月18日

*/

@Component

public class LoginInterceptor extends HandlerInterceptorAdapter {

public final static String ACCESS_TOKEN = "accessToken";

public final static String EXCEPTION_MSG = "signature does not match locally computed signature,error code:";

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

if (!(handler instanceof HandlerMethod)) {

return true;

}

HandlerMethod handlerMethod = (HandlerMethod) handler;

Method method = handlerMethod.getMethod();

RequireSignature methodAnnotation = method.getAnnotation(RequireSignature.class);

// 有 @RequireSignature 注解,需要認證

if (ObjectUtil.isNotNull(methodAnnotation)) {

// 判斷是否存在令牌信息,如果存在,則允許登錄

String accessToken = request.getParameter(ACCESS_TOKEN);

if (StringUtils.isBlank(accessToken)) {

// 需要認證才行

throw new RuntimeException(EXCEPTION_MSG + "400003");

}

Claims claims = null;

try {

claims = TokenUtils.parseJWT(accessToken);

} catch (Exception e) {

throw new RuntimeException(EXCEPTION_MSG + "400005");

}

// 簽名格式錯誤,請按照約定生成簽名

String[] firstParam = claims.getId().split("=");

if (ObjectUtils.isEmpty(firstParam)) {

throw new RuntimeException(EXCEPTION_MSG + "400005");

}

// 簽名被篡改

String parameter = request.getParameter(firstParam[0]);

if (!firstParam[1].equals(parameter)) {

throw new RuntimeException(EXCEPTION_MSG + "400006");

}

boolean validation = false;

// 獲取簽名生成的時間,簽名有效10分鐘

try {

long timeInMillis = DateUtil.calendar(Long.parseLong(claims.get("exp") + "")).getTimeInMillis();

validation = DateUtil.calendar(System.currentTimeMillis())

.getTimeInMillis() < (timeInMillis + 10 * 60 * 1000);

} catch (Exception e) {

throw new RuntimeException(EXCEPTION_MSG + "400005");

}

// 超時

if (validation) {

throw new RuntimeException(EXCEPTION_MSG + "400007");

}

}

return super.preHandle(request, response, handler);

}

}

D。配置攔截器/**

* @Title: ResourceConfig.java

* @Description:

* @Copyright: Copyright (c) 2018

* @Company:http://www.sinocon.cn

* @author Administrator

* @date 2018年8月6日

* @version 1.0

*/

package cn.sinocon.hive.config;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import cn.sinocon.hive.interceptor.LoginInterceptor;

/**

* @Title: ResourceConfig

* @Description:

* @author:Administrator

* @date 2018年8月6日

*/

@Configuration

public class ResourceConfig implements WebMvcConfigurer {

/*

* 默認首頁的設置,當輸入域名是可以自動跳轉到默認指定的網頁

*

*

Title: addViewControllers

*

*

Description:

*

* @param registry

*

* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurer#

* addViewControllers(org.springframework.web.servlet.config.annotation.

* ViewControllerRegistry)

*

*/

@Override

public void addViewControllers(ViewControllerRegistry registry) {

registry.addViewController("/").setViewName("forward:/index.html");

}

/* (non-Javadoc)

*

Title: addInterceptors

*

Description: 攔截器配置

* @param registry

* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurer#addInterceptors(org.springframework.web.servlet.config.annotation.InterceptorRegistry)

*/

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/api/**");

WebMvcConfigurer.super.addInterceptors(registry);

}

}

E、在調用的controller方法中加上注解@RequireSignature

大功告成

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534492.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534492.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534492.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql 5.5.18下載_MySQL5.7.18下載和安裝過程圖文詳解

MySql下載1、打開官網找到下載路口&#xff0c;這里直接給出下載的地址2、選擇64位版本3、直接下載MySql5.7.18.1安裝過程1 、運行安裝軟件&#xff0c;接受協議2、選擇默認安裝3、下一步到檢查環境界面&#xff0c;點擊“Execute”執行檢查 (可以后面單獨下載插件安裝)&…

mysql找不到performance_Mysql安裝完畢運行時沒有mysql和performance_schema數據庫_MySQL

Mysql問題 ERROR 1045 (28000): Access denied for user ‘root’’localhost’ (using password: YES)Mysql安裝完畢運行時沒有 mysql 和 performance_schema 數據庫問題一&#xff1a;之前卸載未卸載干凈問題二&#xff1a;沒有管理員權限進入問題三&#xff1a;登錄時&#…

mysql latid1_mysql觸發器的實戰經驗

1 引言Mysql的觸發器和存儲過程一樣&#xff0c;都是嵌入到mysql的一段程序。觸發器是mysql5新增的功能&#xff0c;目前線上鳳巢系統、北斗系統以及哥倫布系統使用的數據庫均是mysql5.0.45版本&#xff0c;很多程序比如fc-star管理端&#xff0c;sfrd(das)&#xff0c;dorad…

mysql數據庫sql注入原理_SQL注入原理解析以及舉例1

sql注入是指web應用程序對用戶輸入數據的合法性沒有判斷&#xff0c;導致攻擊者可以構造不同的sql語句來實現對數據庫的操作。sql注入漏洞產生滿足條件&#xff1a;1&#xff1b;用戶能夠控制數據的輸入。2&#xff1b;原本需要執行的代碼&#xff0c;拼接了用戶的輸入。舉例&a…

mysql存儲map數據結構_map數據結構

Go map實現原理 - 戀戀美食的個人空間 - OSCHINA - 中文開源技術交流社區 https://my.oschina.net/renhc/blog/2208417// A header for a Go map.type hmap struct {// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.// Make sure this…

四因素三水平正交表_做論文要用正交表?我打包送給你

正交試驗目前在國內的應用量仍然是比較高的&#xff0c;許多高校畢業生喜歡利用正交試驗來獲取研究數據&#xff0c;最終完成畢業論文的撰寫或者期刊投稿。正交試驗方案的設計&#xff0c;必然要用到(標準)正交表。那么大家都是從哪里獲取正交表的呢&#xff1f;小兵給這方面的…

plsql視圖添加表字段_Oracle-單表多字段查詢(不使用*)

環境&#xff1a;Oracle 11g&#xff0c;plsql 14目的&#xff1a;不使用*,查詢擁有上百個字段的表的所有字段。懶人大法&#xff1a;在文章末尾。sql實現邏輯&#xff1a;1、首先建一張100個字段以上的表&#xff0c;通過excel的方式將表建好后直接復制粘貼到plsql的建表界面。…

mysql 編譯安裝與rpm安裝的區別_編譯安裝與RPM安裝的區別

建議在安裝線上的生產服務器軟件包時都用源碼安裝&#xff0c;這是因為源碼安裝可以自行調整編譯參數&#xff0c;最大化地定制安裝結果。這里以MySQL 5線上環境的編譯安裝來說明之&#xff0c;其編譯參數如下所示&#xff1a;./configure-prefix/usr/local/mysql -without-deb…

python字符串變量s的值是python網絡爬蟲_【Python爬蟲作業】-字符串

一、定義字符串變量1.請定義三個字符串a,b,c值分別為 I,like, python2.請將上面三個變量合并輸出I like pythonaIblikecpythonprint(a)print(b)print(c)print(a,b,c)二、定義一個變量 s sdghHhf 1.請先將變量s的空白符去掉 賦值給新變量s1 打印輸出2.請分別將s1變為全部大寫(命…

lableimg閃退_CV學習筆記(二十五):數據集標注與制作

最近在做一些數據標注的工作&#xff0c;雖然標注數據比較枯燥&#xff0c;但這也是每個做算法的工程師升級打怪的必由之路。使用一些合適的工具往往可以事半功倍&#xff0c;效率UP。一&#xff1a;數據標注流程二&#xff1a;數據處理的一些小代碼1&#xff1a;重命名當得到這…

mysql show profile詳解_SQL 性能分析利器 show profile

本文首發個人公眾號《andyqian》, 期待你的關注&#xff5e;前言在之前的文章中&#xff0c;我們提到過一些慢SQL優化的步驟。其中就包括&#xff1a;使用 explain 關鍵字來查看執行計劃&#xff0c;是否命中索引。通過計算某列的區分度&#xff0c;來判斷該列是否適合新建索引…

php判斷給定的整數是否是2的冪_C++_C語言判斷一個數是否是2的冪次方或4的冪次方,快速判斷一個數是否是2的冪次 - phpStudy...

C語言判斷一個數是否是2的冪次方或4的冪次方快速判斷一個數是否是2的冪次方&#xff0c;若是&#xff0c;并判斷出來是多少次方&#xff01;將2的冪次方寫成二進制形式后&#xff0c;很容易就會發現有一個特點&#xff1a;二進制中只有一個1&#xff0c;并且1后面跟了n個0&…

python 包編譯安裝mysql_CentOS7編譯安裝MySQL8.0.23和Python3.1.9

卸載mariadbrpm -qa | grep mariadbmariadb-libs-5.5.64-1.el7.x86_64yum remove mariadb-libs.x86_64 -y安裝高版本GCC&#xff0c;解決編譯中會遇到的GCC 5.3 or newer is required (-dumpversion says 4.8.5)cd /optyum install centos-release-scl -yyum install devtoolse…

python3.0下載用什么瀏覽器_無法讓Python下載網頁源代碼:“不支持瀏覽器版本”...

查看您列出的url&#xff0c;我執行了以下操作&#xff1a;使用wget下載了頁面將urllib與ipython一起使用并下載了頁面使用chrome&#xff0c;只保存了url所有3個都給了我相同的結果文件(相同的大小&#xff0c;相同的內容)。在這可能是因為我沒有登錄&#xff0c;但我確實看到…

java線程堆棧_深入JVM剖析Java的線程堆棧

在這篇文章里我將教會你如何分析JVM的線程堆棧以及如何從堆棧信息中找出問題的根因。在我看來線程堆棧分析技術是Java EE產品支持工程師所必須掌握的一門技術。在線程堆棧中存儲的信息&#xff0c;通常遠超出你的想象&#xff0c;我們可以在工作中善加利用這些信息。我的目標是…

java 文件下載方法_【工具類】Java后臺上傳下載文件的幾種方式

/*** 將本地照片上傳至騰訊云服務上*/public void uploadImage(String localImagePath) throws Exception {// 1.將訂單照片上傳至騰訊地圖眾包側提供的云服務上try {File imageFile new File(localImagePath);if (imageFile.exists()) {String url "http://" map…

java io流讀取txt文件_Java使用IO流讀取TXT文件

通過BufferedReader讀取TXT文件window系統默認的編碼是GBK&#xff0c;而IDE的編碼多數為UTF-8&#xff0c;如果沒有規定new InputStreamReader(new FileInputStream(file),“GBK”)為GBK會出現讀取內容亂碼。//文件路徑String filePath"C:/Users/Admin/Desktop/products.…

c 調用java程序_C ++可以調用Java代碼嗎?

小編典典是的&#xff0c;您當然可以。這是一個例子&#xff1a;這是java文件&#xff1a;public class InvocationHelloWorld {public static void main(String[] args) {System.out.println("Hello, World!");System.out.println("Arguments sent to this pro…

java 大數類_Java大數類介紹

java能處理大數的類有兩個高精度大整數BigInteger和高精度浮點數BigDecimal&#xff0c;這兩個類位于java.math包內&#xff0c;要使用它們必須在類前面引用該包&#xff1a;importjava.math.BigInteger;和importjava.math.BigDecimal;或者importjava.math.*;以下從幾個方面對B…

java 畫樹_java – 如何繪制代表連接節點圖的樹?

我想在Java GUI中顯示樹,但我不知道如何.樹代表連接節點的圖形,如下所示&#xff1a;我應該說我有自己的樹類&#xff1a;public class BinaryTree{private BinaryNode root;public BinaryTree( ){root null;}public BinaryTree( Object rootItem ){root new BinaryNode( roo…