https://blog.csdn.net/qq_36085004/article/details/83348144

API校验

场景

在前后端分离开发时,后端获取数据就是通过异步请求调我们的API接口,但是,如果我们不做安全处理,其他人也可以直接调我们的API,这会让我们的数据泄露。因此,为了让我们的API只能被我们允许的人调用,我们对我们的API进行安全处理,他人在调用我们的API时需要进行校验,符合的才允许调用API。

实现思路

客户端:
调用我们API的人需要用时间戳timestamp,随机字符串noncestr,请求参数以升序排列拼接成一个字符串,并使用MD5进行加密生成一个签名sign。
在发送请求时,将timestamp, noncestr,sign发送给后台

后台:
编写一个拦截器,将所有的请求拦截。
在拦截器中进行请求校验:
1,请求参数sign是否为空,为空返回false。
2,timestamp 加十分钟(超过10分钟请求过期)是否小于服务端当前时间戳,小于返回false。
3,后台获取所有参数,以同样的规则拼接字符串,使用MD5加密,得到一个签名,用得到的签名和请求传来的签名进行比较,相同则放行,不同返回false。

代码

拦截器:
package com.xyy.edlp.intercepter;

import org.springframework.util.DigestUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*; /**
* @Author: perkins
*/
public class ApiSignatureInterceptor extends HandlerInterceptorAdapter { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
Enumeration<String> paramNames = request.getParameterNames();
String timestamp = request.getHeader("timestamp"); long timestampDate = Long.valueOf(timestamp) + 1000*60*10;
long currDate = System.currentTimeMillis();
// 请求过期
if (timestampDate < currDate) {
response.setStatus(403);
return false;
} String noncestr = request.getHeader("noncestr");
String signature = request.getParameter("sign");
System.out.println(signature); if (signature == null) {
response.setStatus(403);
return false;
}
Map map = new HashMap(); //获取所有的请求参数
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
String[] paramValues = request.getParameterValues(paramName); if (paramValues.length > 0) {
String paramValue = paramValues[0];
System.out.println(paramName);
if (paramValue.length() != 0 && !"sign".equals(paramName)) {
map.put(paramName, paramValue);
}
}
} Set setKey = map.keySet();
Object[] keys = setKey.toArray();
// 将请求参数升序排序
Arrays.sort(keys); StringBuilder strBuilder = new StringBuilder();
for (Object str : keys) {
strBuilder.append(str.toString());
strBuilder.append(map.get(str.toString()));
} strBuilder.append("noncestr");
strBuilder.append(noncestr);
strBuilder.append("timestamp");
strBuilder.append(timestamp); System.out.println(strBuilder.toString());
String newSignature = DigestUtils.md5DigestAsHex(strBuilder.toString().getBytes()).toUpperCase(); if (!signature.equals(newSignature)) {
response.setStatus(403);
return false;
}
return true;
}
}
拦截器注册:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new ApiSignatureInterceptor());
}
}

登录token权限验证

场景

系统中,有的api必须用户登陆了才能够调用,因此,必须给这样的api进行安全防护。

实现思路

1,客户端调用登录接口,登录成功,使用JWT生成一个token,将token以UID—token键值对的形式存入redis,返回给客户端一个token和UID。
2,创建一个拦截器,对需要登录权限的接口进行拦截,判断请求中是否有token,根据UID从redis中取出对应的token,对请求中的token进行验证,然后再使用JWT验证token,都没问题放行,否则返回false。

代码

jwt生成token代码
package com.xyy.edlp.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT; import java.io.UnsupportedEncodingException;
import java.util.Date; /**
* @Author: perkins
*/
public class JwtUtil {
private static final String encodeSecretKey = "XX#$%()(#*!()!KL<><MQLMNQNQJQKsdfkjsdrow32234545fdf>?N<:{LWPW"; /**
* token过期时间
*/
private static final long EXPIRE_TIME = 1000 * 60 * 60 * 24 * 7; /**
* 生成token
* @return
*/
public static String createToken(String account) {
try {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(account + encodeSecretKey);
return JWT.create()
.withExpiresAt(date)
.withClaim("account", account)
.sign(algorithm);
} catch (UnsupportedEncodingException e) {
return null;
}
} /**
* 校验token是否失效
* @param token
* @return
*/
public static boolean checkToken(String token, String account) {
try {
Algorithm algorithm = Algorithm.HMAC256(account + encodeSecretKey);
JWTVerifier verifier = JWT.require(algorithm)
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (UnsupportedEncodingException e) {
return false;
}
} /**
* 获取用户account
* @param token
* @return
*/
public static String getAccount(String token){
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("account").asString();
} catch (JWTDecodeException e) {
return null;
}
} }
拦截器代码:
public class JwtInterceptor extends HandlerInterceptorAdapter {

    @Autowired
RedisUtil redisUtil; @Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (token == null) {
response.setStatus(401);
return false;
} String account = JwtUtil.getAccount(token);
String redisToken = redisUtil.get(RedisKey.TP_STORE_KEY + account);
boolean isExpire = JwtUtil.checkToken(token, account); if (redisToken == null || redisToken != token || isExpire) {
response.setStatus(401);
return false;
}
return true;
}
}
拦截器注册:
@Configuration
public class WebConfig implements WebMvcConfigurer { // 再拦截器中使用了RedisUtil bean类,但是拦截器执行实在spring容器bean初始化之前的
// RedisUtil 将无法注入,为了解决该问题,将JwtInterceptor拦截器先配置为一个bean
// 在注册拦截器时,直接使用配置的bean
@Bean
public JwtInterceptor jwtInterceptor(){
return new JwtInterceptor();
} @Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/tp_store/logout");
}
}

Springboot 实现api校验和登录验证的更多相关文章

  1. Springboot 整合ApachShiro完成登录验证和权限管理

    1.前言 做一个系统最大的问题就是安全问题以及权限的问题,如何正确的选择一个安全框架对自己的系统进行保护,这方面常用的框架有SpringSecurity,但考虑到它的庞大和复杂,大多数公司还是会选择 ...

  2. php的api及登录的权限验证

    类,库,接口(APi),函数,这些概念都是根据问题规模的大小来界定的.一个很小的问题肯定没有必要写成一个库,只需要写几句话就行了. 但是比如一个登录验证,这个功能很强大,很通用,可能前台后台都需要用到 ...

  3. Apache Shiro:【2】与SpringBoot集成完成登录验证

    Apache Shiro:[2]与SpringBoot集成完成登录验证 官方Shiro文档:http://shiro.apache.org/documentation.html Shiro自定义Rea ...

  4. 【笔记】vue+springboot前后端分离实现token登录验证和状态保存的简单实现方案

    简单实现 token可用于登录验证和权限管理. 大致步骤分为: 前端登录,post用户名和密码到后端. 后端验证用户名和密码,若通过,生成一个token返回给前端. 前端拿到token用vuex和lo ...

  5. SpringBoot实现基于token的登录验证

    一.SpringBoot实现基于token的登录验证 基于token的登录验证实现原理:客户端通过用户名和密码调用登录接口,当验证数据库中存在该用户后,将用户的信息按照token的生成规则,生成一个字 ...

  6. SpringBoot集成JWT实现token验证

    原文:https://www.jianshu.com/p/e88d3f8151db JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github. ...

  7. Spring Security登录验证流程源码解析

    一.登录认证基于过滤器链 Spring Security的登录验证流程核心就是过滤器链.当一个请求到达时按照过滤器链的顺序依次进行处理,通过所有过滤器链的验证,就可以访问API接口了. SpringS ...

  8. SpringBoot项目搭建 + Jwt登录

    临时接了一个小项目,有需要搭一个小项目,简单记录一下项目搭建过程以及整合登录功能. 1.首先拿到的是一个码云地址,里面是一个空的文件夹,只有一个 2. 拿到HTTPS码云项目地址链接,在IDEA中cl ...

  9. 如何使用新浪微博账户进行应用登录验证(基于Windows Azure Mobile Service 集成登录验证)

    使用三方账号登录应用应该对大家来说已经不是什么新鲜事儿了,但是今天为什么还要在这里跟大家聊这个话题呢,原因很简单 Windows Azure Mobiles Service Authenticatio ...

随机推荐

  1. idea代码提示,不区分大小写

    idea代码提示,不区分大小写:File-->Settings-->Editor-->General-->Code Completion-->Case sensitive ...

  2. RBAC 几种常见的控制权限模型

    1. 几种常见的权限模型 2. ACL 和 RBAC 对比 3. RBAC 权限模型的优势 (1)简化了用户和权限的关系 (2).易于扩展 易于维护 4.优势(给权限和收回权限) 5.架构

  3. JS实现数组去重方法整理

    前言 我们先来看下面的例子,当然来源与网络,地址<删除数组中多个不连续的数组元素的正确姿势> 我们现在将数组中所有的‘ a’ 元素删除: var arr = ['a', 'a', 'b', ...

  4. loj#2049. 「HNOI2016」网络(set 树剖 暴力)

    题意 题目链接 Sol 下面的代码是\(O(nlog^3n)\)的暴力. 因为从一个点向上只会跳\(logn\)次,所以可以暴力的把未经过的处理出来然后每个点开个multiset维护最大值 #incl ...

  5. 微信小程序 text属性设置 WXSS样式

    >微信小程序的布局css样式 参考自  珺L 文字 width: fit-content;font-size:20px;      /*设置文字字号*/color:red;           ...

  6. java的优点和误解 《java核心技术卷i》第一章

    <java核心技术卷i>第一章主要内容包括三点: 1:Java白皮书的关键术语:描述Java的十一个关键字: 2:Java applet 3 :关于Java的常见误解   1:第一章:Ja ...

  7. git 入门教程之安装 git

    安装 git git 目前支持 Linux/Unix.Solaris.Mac和 Windows 平台上运行,根据自身环境选择安装. Linux 系统 linux 系统安装软件大致有两种途径,一种是利用 ...

  8. 根据标签中动态获取的值绑定特定的class

    数据有mock数据获取 mock文件: index文件: 引入文件index: 获取数据函数: 根据获取的标签内容给定不同的样式:

  9. IPerf——网络测试工具介绍与源码解析(5)

    本篇随笔讲述一下TCP协议下,双向测试模式和交易测试模式下客户端和服务端执行的情况: 双向测试模式: 官方文档的解释 Run Iperf in dual testing mode. This will ...

  10. 创建属于其他Session的进程

    创建其他Session(User)的进程需要拿到对应Session的Token作为CreateProcessAsUser的参数来启动进程. 修改有System权限的Token的TokenId为其他Se ...