当前位置: 首页 > news >正文

创建虚拟网站做点击商丘 峰少 seo博客

创建虚拟网站做点击,商丘 峰少 seo博客,宁波网站建设优化服务公司,怎样做旅游网站设计文章目录一、使用背景二、实现方案三、具体流程四、优化五、代码实现六、后续优化一、使用背景 过去对于接口的验证我一般都是直接在登录时为用户发放token,用户在随后的操作中携带了token则允许请求。 但是这样的验证方式存在有一定的问题,如果token被…

文章目录

      • 一、使用背景
      • 二、实现方案
      • 三、具体流程
      • 四、优化
      • 五、代码实现
      • 六、后续优化

一、使用背景

过去对于接口的验证我一般都是直接在登录时为用户发放token,用户在随后的操作中携带了token则允许请求。

但是这样的验证方式存在有一定的问题,如果token被泄露被他人获取,那么就会有非法请求的风险。其他人可以使用这个token自行调用接口进行请求,传入非法参数甚至进行注入攻击等,可能会造成严重的问题。

即存在以下安全问题:

  • 请求身份是否合法
  • 请求参数是否被篡改

为了防止这种情况的发生,我们验证接收到的数据与客户端发送的数据一致,且让接口只能被客户端请求。

二、实现方案

既然要实现接口只能被客户端请求,那么我们不难想到可以与客户端达成某些约定,让客户端按一定的规则发送请求。

只需要服务端与客户端约定一套密钥,客户端在发送请求时拼接上私钥后使用单向加密算法进行加密,服务端收到后使用相同的私钥和加密算法进行加密后验证是否与前端客户端传递的值相同。

这样的方案可以使得用户即使拿到了token没有私钥的话加密后的数据与服务端加密后的肯定不相同而无法通过验证。篡改参数同样会产生相同的问题,从而保证了接口的安全性。

三、具体流程

  • 按照请求参数名的字母升序排列非空请求参数(包含accesskey),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串A;
  • 在字符串A最后拼接上secretkey得到字符串B;
  • 对B进行MD5运算,并将得到的字符串所有字符转换为大写,得到sign值;
  • 携带参数accesskey和sign进行请求

四、优化

以上方式虽然解决了非法用户请求和请求参数被篡改的问题,但是还存在着重复使用请求参数伪造二次请求的隐患。

为了解决这个问题我们不难想到请求时生成一个唯一的标识符,那么服务端在接收到请求之后只需要验证是否已经接受过改请求的标识即可。

不过以上方式还存在一个问题就是服务端要保存那么多的请求标识并不现实,所以我们可以设置一个过期时间,过期了就将标识删除。并让请求的时候携带一个时间戳,超过时间的请求直接打回。

五、代码实现

假设请求接口:test?param1=hello&param2=world

那么前端需要发送请求:test?accesskey=xxx&param1=hello&param2=world&nonce=随机唯一标识&timestamp=当前时间戳&sign=xxx

sign = MD5(“accesskey=xxx&nonce=随机唯一标识&param1=hello&param2=world&secretkey=xxx&timestamp=当前时间戳”).toUpperCase()

注意请求接口中的参数可以不按顺序,而用于生成sign的字符串中的各个参数必须按照一定的顺序(与后端约定)

后端验签:

@Component
public class ApiVerifyUtil {public static final String SECRET_KEY = "secretkey";public static final String ACCESS_KEY = "accesskey";public static final String TIMESTAMP_KEY = "timestamp";public static final String NONCE_KEY = "nonce";public static final String SIGN_KEY = "sign";private static final HashMap<String, String> KEY_PAIR;static {KEY_PAIR = new HashMap<>();KEY_PAIR.put("app1", "password1");  // 为客户端分配的密钥KEY_PAIR.put("app2", "password2");}@Autowiredprivate RedisTemplate<String, String> redisTemplateBean;private static RedisTemplate<String, String> redisTemplate;@PostConstructpublic void init() {redisTemplate = redisTemplateBean;}public static final Integer OK = 0;public static final Integer PARAMS_ERROR = 1;public static final Integer LACK_ACCESSKEY = 2;public static final Integer ACCESSKEY_INVALID = 3;public static final Integer LACK_NONCE = 4;public static final Integer LACK_TIMESTAMP = 5;public static final Integer LACK_SIGN = 6;public static final Integer REQUEST_TIMEOUT = 7;public static final Integer REQUEST_REPEATED = 8;public static final Integer REQUEST_INVALID = 9;// 超时时间(ms)public static final long TIMEOUT = 1000 * 60 * 15;public static final String AND = "&";public static final String EQUALS = "=";public static Integer verify(HashMap<String, String> params) {if (params == null || params.isEmpty()) {return PARAMS_ERROR;}// accessKey为空或不合法(即不存在对应的密钥)或请求参数不全则直接打回String accessKey, secretKey, timestamp, nonce, sign;if ((accessKey = params.get(ACCESS_KEY)) == null) {return LACK_ACCESSKEY;}if ((secretKey = KEY_PAIR.get(accessKey)) == null) {return ACCESSKEY_INVALID;}if ((timestamp = params.get(TIMESTAMP_KEY)) == null) {return LACK_TIMESTAMP;} else if (Long.parseLong(timestamp) - System.currentTimeMillis() > TIMEOUT) {// 超过15分钟return REQUEST_TIMEOUT;}if ((nonce = params.get(NONCE_KEY)) == null) {return LACK_NONCE;} else {Set<String> nonceSet = redisTemplate.opsForSet().members("nonce");if (nonceSet != null && nonceSet.contains(nonce)) {return REQUEST_REPEATED;}}if ((sign = params.get(SIGN_KEY)) == null) {return LACK_SIGN;}params.remove(SIGN_KEY);// 加密需要拼接上密钥params.put(SECRET_KEY, secretKey);ArrayList<String> keyList = new ArrayList<>(params.keySet());// 按顺序构造Collections.sort(keyList);StringBuilder sb = new StringBuilder();for (String key : keyList) {sb.append(key).append("=").append(params.get(key)).append("&");}String newSign = sb.toString();newSign = MD5.create().digestHex16(newSign.substring(0, newSign.length() - 1).toUpperCase());if (newSign.equals(sign)) {redisTemplate.opsForSet().add("nonce", nonce);return OK;}return REQUEST_INVALID;}public static HashMap<String, String> getParams(HttpServletRequest httpServletRequest) {String queryString = httpServletRequest.getQueryString();String[] split = queryString.split(AND);HashMap<String, String> params = new HashMap<>();for (String param : split) {params.put(param.split(EQUALS)[0], param.split(EQUALS)[1]);}return params;}public static HashMap<String, String> getParams(String queryString) {String[] split = queryString.split(AND);HashMap<String, String> params = new HashMap<>();for (String param : split) {params.put(param.split(EQUALS)[0], param.split(EQUALS)[1]);}return params;}}

六、后续优化

  1. 加入接口被调用的阈值限制,对接口访问频率设置一定阈值,对超过阈值的请求进行屏蔽及预警。
  2. 白名单机制:指定一些可以访问我们暴露接口的域名,不在白名单里面的域名发过来的请求,直接拒绝。
http://www.hkea.cn/news/144271/

相关文章:

  • 长沙营销型网站制作费用seo图片优化
  • 学生诚信档案建设网站seo数据分析
  • 北京住房城乡建设厅网站首页1688官网入口
  • 网站建设需要懂什么软件徐州百度seo排名优化
  • wordpress网站样式网站排名查询
  • 郑州网站建设推销外贸网站推广与优化
  • 当当网站开发系统说明搜索引擎排名google
  • 国外男女直接做的视频网站企业邮箱登录入口
  • 成都可以做网站的公司百度手机助手最新版下载
  • 赤峰网站建设招聘市场营销互联网营销
  • 网站开发后端需要哪些技术友情链接检索数据分析
  • 金华竞价排名 金华企业网站建设常见的网络营销平台有哪些
  • p2p网站开发关键词seo是什么意思
  • 自己免费怎么制作网站合肥今天的最新消息
  • 今日头条新闻10条简短seo网络优化招聘信息
  • 赣州人才网官方网站关键词seo优化软件
  • cad做兼职区哪个网站郑州网络营销公司排名
  • 宁夏银川做网站的公司有哪些网络营销分类
  • 换物网站为什么做不起来中国免费广告网
  • 可以显示一张图片的网站怎么搭建搜索引擎优化策略
  • 精品课程网站建设论文今天的新闻最新消息
  • 检查网站收录问题蚌埠seo外包
  • 建站展示网站优化网
  • 秦皇岛网站建设价格深圳seo公司
  • 广告型网站建设广州营销网站建设靠谱
  • 包头学做网站平台开发
  • 个人如何做微商城网站指数分布的分布函数
  • 北京网站设计哪家公司好建站工具
  • 深圳外贸网络推广seo诊断书案例
  • Java做网站的基本框架优化关键词规则