什么是Api接口幂等?
大略来说Api接口幂等在有限的功夫内控制接口考察乞求,控制ip考察度数,不控制平台考察,都不妨拿到数据。一个接口不不妨反复表单提交,消费一次耗费一次。
用户场景:同一功夫反复提交屡次乞求。
什么是数据窜改?
api接口数据窜改,剧本文献,窜改接口参数举行效劳器数据夺取,重要的数据窜改会引导数据库宕机,步调软硬件解体。
想到这边都领会后盾api接口幂等多要害了吧。即日给大师讲非对称加密实行后盾接口api幂等。
实行思绪:jtw+考证标识+出面密钥+暂时功夫戳+寄存过时功夫+AES实行加密算法token。
实行办法:1,用户登录胜利后,消费加密token寄存redis.
2,下次登录检查token能否过时,过时请从新登录。
3,用户登录生存灵验期,不须要登录。(这边即是单点登录办法)
code中心实行类:
importio.jsonwebtoken.*;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;importorg.springframework.security.core.Authentication;importorg.springframework.security.core.GrantedAuthority;importorg.springframework.security.core.authority.SimpleGrantedAuthority;importorg.springframework.security.core.userdetails.User;importorg.springframework.stereotype.Component;importorg.springframework.util.StringUtils;importjavax.annotation.PostConstruct;importjavax.servlet.http.HttpServletRequest;importjava.util.*;importjava.util.stream.Collectors;@ComponentpublicclassJWTTokenUtils{publicstaticfinalStringAUTHORIZATION_HEADER="x-token";publicstaticfinalStringAUTHORIZATION_TOKEN="x-token";privatefinalLoggerlogger=LoggerFactory.getLogger(JWTTokenUtils.class);privatestaticfinalStringAUTHORITIES_KEY="auth";privateStringsecretKey;//出面密钥privatelongtokenValidityInMilliseconds;//作废日子privatelongtokenValidityInMillisecondsForRememberMe;//(记取我)作废日子@PostConstructpublicvoidinit(){this.secretKey="isoftstone.huwei";intsecondIn1day=1000*60*60*24;this.tokenValidityInMilliseconds=secondIn1day*2L;this.tokenValidityInMillisecondsForRememberMe=secondIn1day*7L;}//创造TokenpublicStringcreateToken(Authenticationauthentication,BooleanrememberMe){Stringauthorities=authentication.getAuthorities().stream()//获得用户的权力字符串,如USER,ADMIN.map(GrantedAuthority::getAuthority).collect(Collectors.joining(","));longnow=(newDate()).getTime();//获得暂时功夫戳Datevalidity;//寄存过时功夫if(rememberMe){validity=newDate(now+this.tokenValidityInMilliseconds);}else{validity=newDate(now+this.tokenValidityInMillisecondsForRememberMe);}returnSysConst.SYS_COMPANY_HEAD+"."+Jwts.builder()//创造Token令牌.setSubject(authentication.getName())//树立面向用户.claim(AUTHORITIES_KEY,authorities)//增添权力属性.setExpiration(validity)//树立作废功夫.signWith(SignatureAlgorithm.HS512,secretKey)//天生出面.compact();}//获得用户权力publicAuthenticationgetAuthentication(Stringtoken){logger.info("JWTTokenUtilsStartGetUserAuth");//领会Token的payloadClaimsclaims=Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();Collection<?extendsGrantedAuthority>authorities=Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))//获得用户权力字符串.map(SimpleGrantedAuthority::new).collect(Collectors.toList());//将元素变换为GrantedAuthority接口汇合Userprincipal=newUser(claims.getSubject(),"",authorities);returnnewUsernamePasswordAuthenticationToken(principal,null,authorities);}/***领会token获得用户源代码*@paramtoken*@return*/publicStringgetAuthSubject(Stringtoken){Claimsclaims=Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();returnclaims.getSubject();}publicStringresolveToken(HttpServletRequestrequest){StringbearerToken=request.getHeader(AUTHORIZATION_HEADER);//从HTTP头部获得TOKENif(StringUtils.hasText(bearerToken)&&bearerToken.startsWith(SysConst.SYS_COMPANY_HEAD)){returnbearerToken.substring(bearerToken.indexOf(".")+1,bearerToken.length());//归来Token字符串,去除Bearer}Stringjwt=request.getParameter(AUTHORIZATION_TOKEN);//从乞求参数中获得TOKENif(StringUtils.hasText(jwt)&&jwt.startsWith(SysConst.SYS_COMPANY_HEAD)){returnjwt.substring(bearerToken.indexOf(".")+1,jwt.length());}returnnull;}//考证Token能否精确publicbooleanvalidateToken(Stringtoken){try{Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);//经过密钥考证Tokenreturntrue;}catch(MalformedJwtExceptione){//JWT***缺点logger.info("InvalidJWTtoken.");logger.trace("InvalidJWTtokentrace:{}",e);}catch(ExpiredJwtExceptione){//JWT过时logger.info("ExpiredJWTtoken.");logger.trace("ExpiredJWTtokentrace:{}",e);}catch(UnsupportedJwtExceptione){//不扶助该JWTlogger.info("UnsupportedJWTtoken.");logger.trace("UnsupportedJWTtokentrace:{}",e);}catch(IllegalArgumentExceptione){//参数缺点特殊logger.info("JWTtokencompactofhandlerareinvalid.");logger.trace("JWTtokencompactofhandlerareinvalidtrace:{}",e);}catch(SignatureExceptione){//出面特殊logger.info("InvalidJWTsignature.");logger.trace("InvalidJWTsignaturetrace:{}",e);}returnfalse;}}redis写入缓存:
RedisModelmodel=newRedisModel();model.setModelName(token);model.setModelKey("userInfo");Map<String,Object>params=newHashMap<String,Object>();params.put("userName",customerDto.getUsername());CustomerVocustomerVo=newCustomerVo();customerVo.setEmail(customerDto.getEmail());customerVo.setPhone(customerDto.getPhone());CustomerVouserInfo=customerService.queryUserByUserName(customerVo);Map<String,Object>userToken=newHashMap<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)publicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{publicstaticfinalStringAUTHORIZATION_HEADER="x-token";//Authorization//承诺考察的路途privatestaticfinalString[]AUTH_WITHOUTLIST={//--swaggerui"/v2/api-docs","/swagger-resources","/swagger-resources/**","/configuration/ui","/configuration/security","/swagger-ui.html","/webjars/**",//otherpublicendpointsofyourAPImaybeappendedtothisarray"/druid/**","/health","/info","/info/**",//druidsql监听"/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/***s/sendPhone","/citry/getChineseProvinces","/code/getCaptchaImage","/u/***s/forgetEmailPwd","/u/***s/sendEmail","/citry/getOtherCoutryList","/upload/pngDir/*","/job/getJobList","/u/***s/sendLoginEmail","/v1/authcenter/queryUserInfoByMap","/v1/authcenter/forgetPwd","/diagram-viwmer/**","/editor-marketing/**","/modeler.html","/actuator/health"};@AutowiredprivateSecurityUserDetailsServicesecurityUserDetailsService;@AutowiredprivateAuthLogoutSuccessHandlerauthLogoutSuccessHandler;@AutowiredprivateJWTTokenUtilstokenProvider;@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{//自设置获得用户消息树立暗号加密和默许用DaoAuthenticationProvider加密任选auth.userDetailsService(securityUserDetailsService).passwordEncoder(passwordEncoder());}@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{//摆设乞求考察战略//封闭CSRF、CORShttp.cors().disable().csrf().disable()//因为运用Token,以是不须要Session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()//考证Http乞求.authorizeRequests()//承诺一切用户考察首页与登录.antMatchers(AUTH_WITHOUTLIST).permitAll()//其它任何乞求都要过程认证经过.anyRequest().authenticated().and()//用户页面须要用户权力//树立登出.logout().logoutSuccessHandler(authLogoutSuccessHandler).permitAll();//增添JWTfilter在http.addFilterBefore(newJwtAuthenticationTokenFilter(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":%