篡改常识的系统最新章节(网站防篡改设备)

什么是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接口幂等就实现完成了。

发布于 2022-03-01 11:50:40
收藏
分享
海报
0 条评论
175
上一篇:最强md5解密工具(在线md5解密工具) 下一篇:android常用控件大全(android时间选择控件大全)
目录

    推荐阅读

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码