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
大功告成
restfull加签_SpringBoot RestFull API签名相关推荐
- RSA对数据进行加签和验签
rsa有两个非常重要的作用:加密和加签 加密时用公钥加密,私钥解密. 加签时用私钥加签,公钥验证签名. 加签的目的: 验证信息的发送方是否正确,信息是否被其他人篡改. 加密的目的: 保证信息的隐私,不 ...
- 利用md5加密实现API接口的加签验签
1.背景 我现在有几个公开的接口需要开放给第三方厂商,第三方厂商通过调用我的接口获取数据,由于这些接口放开了登录的拦截,而且是直接暴露在公网上的,因此想给这几个接口加上权限的验证,即加签验签. 2.技 ...
- java支付宝rsa2签名,使用支付宝SDK进行RSAj加签验签以及加密解密
/** * 支付宝 sdk 加签验签测试 * * @author 码农猿 */ public class SignDemo { /** * 公钥 */ private static final Str ...
- RSA签名加签、验签实现
一.引言 之前简单写了一个关于参数名ASCII码从小到大排序的文章(https://blog.csdn.net/sinat_34974437/article/details/104756995),该方 ...
- 淘东电商项目(68) -互联网安全架构设计(黑名单拦截及MD5加签)
引言 本文代码已提交至Github(版本号:d439ec96b39dc0adf0d697cbc6bfc87c1c3b7dc8),有兴趣的同学可以下载来看看:https://github.com/ylw ...
- 聊一聊关于加解密、加签验签的那些事
面对MD5.SHA.DES.AES.RSA等等这些名词你是否有很多问号?这些名词都是什么?还有什么公钥加密.私钥解密.私钥加签.公钥验签.这些都什么鬼?或许在你日常工作没有听说过这些名词,但是一旦你要 ...
- 速看: 加解密、加签验签,你想要的都在这了
点击蓝色"java大数据修炼之道"关注我哟加个"星标",每晚21:00,一起学技术 来源: jianshu.com/p/5e9fe1fff6a3 作者: 不学无 ...
- 前后端RSA互相加解密、加签验签、密钥对生成(Java)
目录 一.序言 二.关于PKCS#1和PKCS#8格式密钥 1.简介 2.区别 二.关于JSEncrypt 三.关于jsrsasign 四.前端RSA加解密.加验签示例 1.相关依赖 2.crypto ...
- 安全对外的接口--加签验签
前言 我们在求职面试中,经常会被问到,如何设计一个安全对外的接口呢? 其实可以回答这一点,加签和验签,这将让你的接口更加有安全.接下来,本文将和大家一起来学习加签和验签.从理论到实战,加油哦~ 密码学 ...
最新文章
- IBM携手天健“漫步”区域医疗信息化市场
- 第十六届智能车竞赛赛道电磁线圈铺设方法
- div居中 边框设置 文字行高设置
- 带参数的过滤器|| 过滤器案例:格式化日期|| time.js ||
- NYOJ 714 Card Trick
- 10-NSPersistentContainer介绍
- 别给小偷可乘之机!日本山形县警方呼吁民众“锁门”
- 【渝粤题库】陕西师范大学210019 学前教育科研方法 作业(专升本)
- UVA	11549 Calculator Conundrum
- 单片机C语言稳压程序,51单片机的基于MC34063的5V稳压器的设计 -(原理图+程序)...
- Jboss 安装配置
- Step by Step WebMatrix网站开发之一:Webmatrix安装
- 测试工程师必备小工具指南
- bat: 调用WinRAR.exe压缩文件
- PMP 风险应对措施 :规避和减轻的区别
- 这几个免费、商用图片素材网,你一定要知道。
- c# meiju(摘)
- 信用社考试计算机试题及答案,2016黑龙江省农村信用社考试题库-计算机试题及答案六...
- excel提取括号内的内容
- 哪些机型适配了android11,coloros11适配机型_coloros11支持机型有哪些
热门文章
- 关于在nw里使用require('printer')和nw.require('printer')报错的问题
- 08服务器许可证安装向导,08_安装部署GRID许可证服务器.pdf
- qt最大化和还原实现_研究进展 | 水生所关于细菌异化型硝酸盐还原成铵与反硝化脱氮两种途径抉择的分子调控机制研究取得进展...
- cocos android-1,Cocos2D-Android-1之源码详解:5.Box2dTest
- 主站系统服务器选择,配电网自动化主站系统的结构_功能及操作系统的选择.doc...
- android获取操作系统版本号,Android 获取手机的厂商、型号、Android系统版本号、IMEI、当前系统语言等工具类...
- python换源还是不行_浅析Python3 pip换源问题
- linux中控和安卓中控哪个比较好,原厂中控和改装中控有什么区别?哪个更好?...
- ajax保存避免重复提交,ajax 实现防止重复提交
- 浙江高校计算机等级考试二级办公,浙江省高校计算机等级考试二级(高级办公)Word操作提示.doc...