篡改常识的系统最新章节(网站防篡改设备)
什么是Api接口幂等?
简单来说Api接口幂等在有限的时间内限制接口访问请求,限制ip访问次数,不限制平台访问,都可以拿到数据。一个接口不可以重复表单提交,生产一次消费一次。
用户场景:同一时间重复提交多次请求。
什么是数据篡改?
api接口数据篡改,脚本文件,篡改接口参数进行服务器数据窃取,严重的数据篡改会导致数据库宕机,程序软件崩溃。
想到这里都知道后台api接口幂等多重要了吧。今天给大家讲非对称加密实现后台接口api幂等。
实现思路:jtw+ 验证标识+签名密钥+当前时间戳+存放过期时间+AES 实现加密算法token。
实现步骤:1,用户登录成功后,生产加密token存放redis.
2,下次登录检验token 是否过期,过期请重新登录。
3,用户登录存在有效期,不需要登录。(这里就是单点登录方式)
code核心实现类:
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class JWTTokenUtils {
public static final String AUTHORIZATION_HEADER = "x-token";
public static final String AUTHORIZATION_TOKEN = "x-token";
private final Logger logger = LoggerFactory.getLogger(JWTTokenUtils.class);
private static final String AUTHORITIES_KEY = "auth";
private String secretKey; // 签名密钥
private long tokenValidityInMilliseconds; // 失效日期
private long tokenValidityInMillisecondsForRememberMe; // (记住我)失效日期
@PostConstruct
public void init() {
this.secretKey = "isoftstone.huwei";
int secondIn1day = 1000 * 60 * 60 * 24;
this.tokenValidityInMilliseconds = secondIn1day * 2L;
this.tokenValidityInMillisecondsForRememberMe = secondIn1day * 7L;
}
// 创建Token
public String createToken(Authentication authentication, Boolean rememberMe) {
String authorities = authentication.getAuthorities().stream() // 获取用户的权限字符串,如 USER,ADMIN
.map(GrantedAuthority::getAuthority).collect(Collectors.joining(","));
long now = (new Date()).getTime(); // 获取当前时间戳
Date validity; // 存放过期时间
if (rememberMe) {
validity = new Date(now + this.tokenValidityInMilliseconds);
} else {
validity = new Date(now + this.tokenValidityInMillisecondsForRememberMe);
}
return SysConst.SYS_COMPANY_HEAD+"."+ Jwts.builder() // 创建Token令牌
.setSubject(authentication.getName()) // 设置面向用户
.claim(AUTHORITIES_KEY, authorities) // 添加权限属性
.setExpiration(validity) // 设置失效时间
.signWith(SignatureAlgorithm.HS512, secretKey) // 生成签名
.compact();
}
// 获取用户权限
public Authentication getAuthentication(String token) {
logger.info("JWTTokenUtils Start Get User Auth");
// 解析Token的payload
Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
Collection<? extends GrantedAuthority> authorities = Arrays
.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) // 获取用户权限字符串
.map(SimpleGrantedAuthority::new).collect(Collectors.toList()); // 将元素转换为GrantedAuthority接口集合
User principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, null, authorities);
}
/**
* 解析token获取用户编码
* @param token
* @return
*/
public String getAuthSubject(String token) {
Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
return claims.getSubject();
}
public String resolveToken(HttpServletRequest request){
String bearerToken = request.getHeader(AUTHORIZATION_HEADER); //从HTTP头部获取TOKEN
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(SysConst.SYS_COMPANY_HEAD)){
return bearerToken.substring(bearerToken.indexOf(".")+1, bearerToken.length()); //返回Token字符串,去除Bearer
}
String jwt = request.getParameter(AUTHORIZATION_TOKEN); //从请求参数中获取TOKEN
if (StringUtils.hasText(jwt) && jwt.startsWith(SysConst.SYS_COMPANY_HEAD)) {
return jwt.substring(bearerToken.indexOf(".")+1, jwt.length());
}
return null;
}
// 验证Token是否正确
public boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); // 通过密钥验证Token
return true;
} catch (MalformedJwtException e) { // JWT格式错误
logger.info("Invalid JWT token.");
logger.trace("Invalid JWT token trace: {}", e);
} catch (ExpiredJwtException e) { // JWT过期
logger.info("Expired JWT token.");
logger.trace("Expired JWT token trace: {}", e);
} catch (UnsupportedJwtException e) { // 不支持该JWT
logger.info("Unsupported JWT token.");
logger.trace("Unsupported JWT token trace: {}", e);
} catch (IllegalArgumentException e) { // 参数错误异常
logger.info("JWT token compact of handler are invalid.");
logger.trace("JWT token compact of handler are invalid trace: {}", e);
}catch (SignatureException e) { // 签名异常
logger.info("Invalid JWT signature.");
logger.trace("Invalid JWT signature trace: {}", e);
}
return false;
}
}
redis写入缓存:
RedisModel model = new RedisModel();
model.setModelName(token);
model.setModelKey("userInfo");
Map<String,Object> params = new HashMap<String,Object>();
params.put("userName", customerDto.getUsername());
CustomerVo customerVo = new CustomerVo();
customerVo.setEmail(customerDto.getEmail());
customerVo.setPhone(customerDto.getPhone());
CustomerVo userInfo = customerService.queryUserByUserName(customerVo);
Map<String,Object> userToken = new HashMap<String,Object>();
userToken.put("userToken", token);
userToken.put("userInfo", userInfo);
model.setModelData(userToken);
model.setTimeoutType("M");
model.setTimeout(redisTokenTimeOut);
resultMap.setCode(CommonResultStatus.SUCCESS.getCode());
resultMap.setMessage(CommonResultStatus.SUCCESS.getMessage());
//写入为hash实体
redisTemplate.opsForHash().put(model.getModelName(), model.getModelKey(), model.getModelData());
redisTemplate.expire(model.getModelName(), model.getTimeout(), TimeUnit.MINUTES);
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public static final String AUTHORIZATION_HEADER = "x-token";//Authorization
//允许访问的路径
private static final String[] AUTH_WITHOUTLIST = {
// -- swagger ui
"/v2/api-docs", "/swagger-resources", "/swagger-resources/**", "/configuration/ui",
"/configuration/security", "/swagger-ui.html", "/webjars/**",
// other public endpoints of your API may be appended to this array
"/druid/**","/health","/info","/info/**",//druid sql 监听
"/hystrix","/hystrix/**","/error","/loggers","/loggers/**",
"/service-registry/instance-status","/hystrix.stream","/turbine/**","/turbine.stream",
"/autoconfig","/archaius","/beans","/features","/configprops","/mappings","/auditevents",
"/env","/env/**","/metrics","/metrics/**","/trace","/trace/**", "/dump","/dump/**", "/jolokia/**",
"/info/**","/activiti/**", "/logfile/**", "/refresh","/flyway/**", "/liquibase/**","/heapdump","/heapdump/**",
"/v1/authcenter/login","/v1/authcenter/fiberhomeLogin","/v1/authcenter/registered",//登录URL
"/v1/authcenter/queryAuthInfo",//鉴权URL
"/u/sms/sendPhone","/citry/getChineseProvinces","/code/getCaptchaImage","/u/sms/forgetEmailPwd",
"/u/sms/sendEmail","/citry/getOtherCoutryList","/upload/pngDir/*","/job/getJobList","/u/sms/sendLoginEmail",
"/v1/authcenter/queryUserInfoByMap","/v1/authcenter/forgetPwd",
"/diagram-viwmer/**","/editor-marketing/**",
"/modeler.html",
"/actuator/health"
};
@Autowired
private SecurityUserDetailsService securityUserDetailsService;
@Autowired
private AuthLogoutSuccessHandler authLogoutSuccessHandler;
@Autowired
private JWTTokenUtils tokenProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//自定义获取用户信息设置密码加密 和默认用DaoAuthenticationProvider加密任选
auth.userDetailsService(securityUserDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置请求访问策略
// 关闭CSRF、CORS
http.cors().disable().csrf().disable()
// 由于使用Token,所以不需要Session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 验证Http请求
.authorizeRequests()
// 允许所有用户访问首页 与 登录
.antMatchers(AUTH_WITHOUTLIST).permitAll()
// 其它任何请求都要经过认证通过
.anyRequest().authenticated().and()
// 用户页面需要用户权限
// 设置登出
.logout().logoutSuccessHandler(authLogoutSuccessHandler).permitAll();
// 添加JWT filter 在
http.addFilterBefore(new JwtAuthenticationTokenFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
}
//判断是否有权限分三步
后台security 已经对地址做了拦截了,请求头必须设置请求参数参数
1:判断token是否存在(security 已实现)
2:token是否有效(基于redis)
3:访问API是否有权限
缓存结构:
[
"java.util.HashMap",
{
"userToken": "ISOFTSTONE.eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0MmRkMGJlZmQwNDg0MmMyODhiN2QxZjVkYTcwMWNjNiIsImF1dGgiOiJ1c2VyIiwiZXhwIjoxNjM1MjMyMzk4fQ.9VqMD0vyu-pe42moNd1QeNWP4KrBvvNYJKDQdQPDi_YKKXPG3l90dNn5wgK2rZXs471Pmeby-BdHPHd2-iNKfA",
"userInfo": [
"com.common.vo.CustomerVo",
{
"id": "42dd0befd04842c288b7d1f5da701cc6",
"createTime": [
"java.util.Date",
"2021-06-10"
],
"updateTime": [
"java.util.Date",
"2021-06-10"
],
"deleted": 0,
"phone": "13797004616",
"password": "123456",
"email": "sunlin@fiberhome.com",
"status": "3",
"isEnable": "1",
"userType": "1",
"roleId": null,
"country": null,
"provinces": null,
"company": null,
"jobs": null,
"realName": "孙",
"fiberhomeEmail": null,
"department": null,
"registerWay": null,
"onlineTime": null,
"expireDate": null,
"registerIp": null,
"language": null,
"equipmentType": null,
"accountType": null,
"platformType": null,
"companyType": null,
"userdesc": null,
"userid": "0210990342",
"typeConfig": null,
"isActive": "1",
"postname": "副总经理",
"did1": "701387",
"dname1": "财务管理部",
"did2": null,
"dname2": null,
"did3": null,
"dname3": null,
"did4": null,
"dname4": null,
"postid": "803711"
}
]
}
]
接口实现返回:
x-token:ISOFTSTONE.eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0MmRkMGJlZmQwNDg0MmMyODhiN2QxZjVkYTcwMWNjNiIsImF1dGgiOiJ1c2VyIiwiZXhwIjoxNjM1MjMyNTMzfQ.4QzaY_ln-EVukG6Hnbx-mRl2nUB0Eu6jJxIN0KHigzLfqZH7aXt1aId0RhRvS-o5Vf7cVp5jd9cqpkQwfp724A
请求其他接口访问,加入到请求头Headers里面即可。我们的api接口幂等就实现完成了。
推荐阅读
-
洗衣机不脱水了是怎么回事(洗衣机不甩干的处理方法)
洗衣机作为大家日常生活必备的家用电器,其利用率频繁,难免会因为机械磨损、缺乏润滑油、机件老化、弹簧疲劳变形等原因,出现各种不正...
-
电子表格零基础自学教程(小白也能学明白)
可能很多人(包括我)觉得Excel不就是做个表吗,没什么好学的。然而很多大型企业在面试的时候还是会问,“会Excel吗?”“会...
-
笔记本电脑报价大全(联想笔记本多少钱)
(注意:建议在旗舰店、官方旗舰店、官网购买) 一、游戏本设计本、办公本推荐如下: 华为品牌:(全球第一大电信设备商) 1...
-
煲机软件哪个好(让耳机有个思想准备)
《无间道》中陈永仁与刘建明有过一句经典对白&mdash;&mdash;“高音甜、中音准、低音沉,总之一个词通透”。这一句话也一...
-
viewsonic平板电脑(viewsonic平板电脑刷机)
ViewSonic是一个视讯品牌,中文名字:优派。 ViewSonic 一、读音:英[vju:][?s?n?k],美[vj...
-
采访麦克风户外哪款好(讯飞智能无线麦克风C1采访神器)
对于视频创作者、直播工作者、远程培训老师、记者等媒体工作者来说,工作过程中,最让人费心的莫过于如何确保收音纯正、字幕快速生成、...
-
电脑硬件配置怎么查(详述两招快速查看电脑配置参数信息)
大家好,今天跟大家分享两个快速查看电脑配置参数信息的办法。 操作步骤如下: 1右击电脑屏幕最下方任务栏左侧的电脑徽标按钮,...
-
数据线没坏但充不上电怎么办(数据线充不上电处理方法)
苹果充电器突然充不上电是比较尴尬的问题,首先看自己的充电器数据线是不是原装,如果非原装在第一次充电时,苹果手机会提示你是否要适...
-
电脑开机出现黑屏如何处理(电脑不能开机黑屏解决方法)
电脑不能开机或者开机以后黑屏怎么解决?这里收集了所有常见的维修方法,看完秒变维修高手,实在是一篇不能错过的电脑维修教程。简单易...
-
手机宝典怎么搞(小米手机性能优化宝典)
别再总是抱怨手机卡顿,系统臃肿,反应慢,现在看完这篇文章,你会发现你并不了解小米手机,当然,文中许多方法并不是仅仅适用于小米手...