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

让网站对搜索引擎友好营销软文网站

让网站对搜索引擎友好,营销软文网站,网站重购,做外贸网站那个平台好前言 一、接口安全的方式   1. 身份认证#xff0c;鉴别客户端   2. 请求过程鉴权#xff0c;防止请求被篡改   3. 访问控制#xff0c;即控制客户端对API的访问权限 前言 某家电商平台上#xff0c;用户可以通过客户端发起购物请求#xff0c;并对所选商品进行下…前言 一、接口安全的方式   1. 身份认证鉴别客户端   2. 请求过程鉴权防止请求被篡改   3. 访问控制即控制客户端对API的访问权限 前言 某家电商平台上用户可以通过客户端发起购物请求并对所选商品进行下单、支付等操作。 为了保障系统的安全性和用户隐私该电商平台采取了一系列安全措施包括身份认证、请求过程鉴权和访问控制等三个阶段的验证。 第一阶段是身份认证鉴别客户端的身份。这一阶段可以采用多种方式进行身份验证如HTTP基本认证、Token认证和OAuth2认证等。在具体实践中我们可以在客户端请求接口的时候一并提交用于身份认证的Token信息接口服务器可以通过相关的算法验证Token合法性并拒绝非法请求。同时Token的生成和管理可利用第三方模块如jsonwebtoken等来实现。 第二阶段是请求过程鉴权防止请求被篡改。针对您提供的拉起第三方支付的业务场景可以在客户端请求前提前生成一份用于防伪验签的随机字符串或者签名然后将该随机字符串或者签名等信息携带在接口请求参数中客户端请求接口时后端可以将请求参数中的随机字符串或者签名等信息重新计算一遍以判断请求是否被篡改。在具体实现中我们可以需要将关键数据通过客户端的公钥或者密钥进行加密后再发送到后端服务器上以保证隐私数据不会被泄露。 第三阶段是访问控制即控制客户端对API的访问权限。在具体实践中我们可以利用RBAC模型对访问API的权限进行控制。RBAC模型的基本思想是将访问API的用户分为多个角色然后对每个角色授予对API的访问权限。当用户访问API时后端服务器会根据该用户被授予的角色来判断用户是否有权访问该API如果没有授权访问权限则服务器会拒绝请求。 以下是Java版本的接口验签示例代码 import java.security.MessageDigest; import java.util.Map;import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController;RestController public class PaymentController { private final String APP_SECRET xxx;RequestMapping(/third_party_payment) ResponseBody public String third_party_payment(RequestParam MapString, String params) { String appId params.get(app_id); String timestamp params.get(timestamp); String paymentAmount params.get(payment_amount); String sign params.get(sign);// 进行参数合法性校验 if (StringUtils.isEmpty(appId) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(paymentAmount) || StringUtils.isEmpty(sign)) { return {code:400,msg:参数不完整。}; }// 进行接口鉴权校验 String data String.format(%s%s%s%s, appId, timestamp, paymentAmount, APP_SECRET); String md5Sign MD5(data); if (!md5Sign.equals(sign)) { return {code:400,msg:签名不正确。}; } // 成功的业务逻辑处理 return {code:200,msg:ok}; }/** * 计算MD5值 */ private String MD5(String data) { try { MessageDigest md MessageDigest.getInstance(MD5); byte[] bytes md.digest(data.getBytes(UTF-8)); StringBuilder sb new StringBuilder(); for (byte b : bytes) { String hex Integer.toHexString(b 0xff); if (hex.length() 1) { sb.append(0); } sb.append(hex); } return sb.toString(); } catch (Exception e) { throw new RuntimeException(e); } } } 在该实现中我们使用SpringBoot作为应用开发框架通过RESTful API的方式提供第三方支付接口服务。接口请求时需要提供app_id、timestamp、payment_amount和sign四个参数其中sign参数是通过对前三个参数进行加密生成的。我们使用了MD5算法对前三个参数和app_secret进行加密生成sign参数。请求到达服务端后我们可以通过鉴别请求参数的合法性来进行身份认证和请求过程鉴权接着可以使用MD5算法对请求参数进行处理判断请求是否被篡改。最后我们对用户的请求进行业务逻辑处理并返回对应的结果。 总的来说该实现使用了常见的开发框架和加密算法实现了基本的接口验策略。在实际应用中需要结合具体业务场景进行优化和改进以保证接口的安全性、可靠性和高效性。 常见的案例 输入验证 输入验证是保证接口安全性的重要措施之一可以使用正则表达式或其他验证方式对请求参数进行验证确保数据的完整性和正确性。以下是一个简单的示例代码 RequestMapping(value /login, method RequestMethod.POST) public ResponseEntityString login(RequestParam(username) String username, RequestParam(password) String password) { // 验证用户名是否合法 if (!username.matches(^[a-zA-Z0-9]*$)) { return new ResponseEntity(Invalid username, HttpStatus.BAD_REQUEST); } // 验证密码是否合法 if (!password.matches(^[a-zA-Z0-9]*$)) { return new ResponseEntity(Invalid password, HttpStatus.BAD_REQUEST); } // TODO: 根据具体业务逻辑进行其他验证 return new ResponseEntity(Login success, HttpStatus.OK); } 复制代码 防止SQL注入 SQL注入是常见的攻击手段之一可以通过参数化查询或预编译语句来防止SQL注入攻击。以下是一个简单的示例代码 RequestMapping(value /users, method RequestMethod.GET) public ResponseEntityListUser getUsers(RequestParam(name) String name) { String sql SELECT * FROM user WHERE name ?; ListUser users jdbcTemplate.query(sql, new Object[]{name}, new BeanPropertyRowMapper(User.class)); return new ResponseEntity(users, HttpStatus.OK); } 复制代码 防止XSS攻击 XSS攻击是指攻击者在页面中注入恶意脚本可以通过对特殊字符进行转义或使用HTML5的Content Security Policy来防止XSS攻击。以下是一个简单的示例代码 RequestMapping(value /search, method RequestMethod.GET) public ResponseEntityString search(RequestParam(keyword) String keyword) { // 对特殊字符进行转义 keyword HtmlUtils.htmlEscape(keyword); // TODO: 根据具体业务逻辑进行查询 return new ResponseEntity(result, HttpStatus.OK); } 复制代码 4. 防止CSRF攻击 CSRF攻击是指攻击者利用用户的登录状态发起恶意请求可以通过在请求中添加随机生成的CSRF令牌来防止CSRF攻击。以下是一个简单的示例代码 RequestMapping(value /transfer, method RequestMethod.POST) public ResponseEntityString transfer(RequestParam(from) String from, RequestParam(to) String to, RequestParam(amount) BigDecimal amount, RequestParam(csrfToken) String csrfToken, HttpServletRequest request) { // 验证CSRF令牌 HttpSession session request.getSession(); String sessionToken (String) session.getAttribute(csrfToken); if (!csrfToken.equals(sessionToken)) { return new ResponseEntity(Invalid CSRF token, HttpStatus.BAD_REQUEST); } // TODO: 根据具体业务逻辑进行转账 return new ResponseEntity(Transfer success, HttpStatus.OK); } RequestMapping(value /getCSRFToken, method RequestMethod.GET) public ResponseEntityString getCSRFToken(HttpServletRequest request) { // 生成随机的CSRF令牌 String csrfToken UUID.randomUUID().toString(); HttpSession session request.getSession(); session.setAttribute(csrfToken, csrfToken); return new ResponseEntity(csrfToken, HttpStatus.OK); } 复制代码 5. 验证UID是否是登录UID 验证UID是否是登录UID也是保证接口安全性的重要措施之一。在实际开发中我们通常会使用会话机制session来保存用户的登录状态。对于需要验证UID的接口我们可以在会话中保存用户的UID并在接口调用时进行验证确保用户只能访问自己的数据。以下是一个简单的示例代码 RequestMapping(value /getUserInfo, method RequestMethod.GET) public ResponseEntityUserInfo getUserInfo(RequestParam(uid) Long uid, HttpSession session) { // 验证用户是否登录 Long loginUid (Long) session.getAttribute(uid); if (loginUid null) { return new ResponseEntity(HttpStatus.UNAUTHORIZED); } // 验证UID是否是登录UID if (!uid.equals(loginUid)) { return new ResponseEntity(HttpStatus.FORBIDDEN); } // TODO: 根据UID获取用户信息 UserInfo userInfo userService.getUserInfo(uid); return new ResponseEntity(userInfo, HttpStatus.OK); } 复制代码 在实际开发中以上安全措施可能只是保障接口安全的基础还需要根据具体的业务场景和安全需求进行进一步的加固。以下是一些额外的安全措施 HTTPS采用HTTPS协议保障接口传输的安全性防止中间人攻击和数据泄露。 API密钥为每个客户端分配唯一的API密钥防止未经授权的访问。 访问频率限制限制接口访问的频率防止恶意攻击和DDoS攻击。 日志记录记录接口的访问日志和异常日志方便追踪和排查安全问题。 安全审计定期对接口进行安全审计发现可能存在的安全漏洞并及时修复。 防火墙在服务器上配置防火墙限制对接口的访问防止未经授权的访问和攻击。 综上所述保障接口安全需要采取一系列的安全措施包括输入验证、防止SQL注入、防止XSS攻击、防止CSRF攻击、验证UID是否是登录UID等。除此之外还可以采取其他的安全措施来进一步加固接口的安全性确保接口的稳定和安全。 一、为什么要保证接口安全 在我们日常开发中,存在一些接口是敏感且重要的,比如充值接口,如果在你调用充值接口的时候被别人抓包了,然后就可以修改充值的金额,本来充值10元可以改成充值10w,产生重大生产问题,再或者说被被人抓包了,别人可以不限制的调用该充值10元的接口,调用几万次,也是会导致重大问题,那么我们该如何保证接口安全呢? 二、接口安全的几种方式 2.1 数据参数合法性校验 接口数据的安全性保证还需要我们的系统有个数据合法性校验简单来说就是参数校验比如身份证长度手机号长度是否是数字等等 2.2 token授权认证方式 一般我们系统都会使用token鉴权登陆校验用户登陆状态和用户权限,访问接口前先校验token的合法性 2.3 数据加密,防止报文明文传输 说到数据加密,我们不难想到使用HTTPS进行传输,HTTPS使用了RSA和AES加密的方式保证了数据传输中的安全问题,具体的HTTPS的加密原理,请看HTTPS原理 数据在传输过程中被加密了理论上即使被抓包数据也不会被篡改。但是https不是绝对安全的哦。还有一个点https加密的部分只是在外网然后有很多服务是内网相互跳转的签名验证也可以在这里保证不被中间人篡改所以一般转账类安全性要求高的接口开发都需要加签验签 2.4 签名验证 https虽然保证了在外网上数据不会被篡改,但是不能保证在内网中数据篡改的风险,所以需要有签名验证的环节 客户端把参数以特定顺序进行md5加密形成签名sign,一并同参数传递到服务端 服务端接收到签名和参数,也以一定的顺序对参数进行md5加密,对比传递来的sign判断是否是否被篡改 这样做的好处就是,在数据传输过程中,可以保证数据不会被篡改,如果篡改了的话sign就会不一致,验证不通过 但是这仅仅只是解决了篡改问题,那如果我拿到请求后不修改参数,原样数据多次调用,还是会产生问题,这时候就需要增加防重放功能 2.5 timestampnonce方案防止重放攻击 timestamp是时间戳超时机制,当一个请求超过该时间后,则认定为该请求失效,需要重新发送请求,默认60s,但是如果在60s内多次调用岂不是也会导致问题? 通常来说,从抓包到重放的时间绝对不止60s,为了避免此类问题发生,我们可以在客户端发送请求的时候随机产生一个nonce随机数 nonce令牌是一个随机数,每次请求后都会存入redis,过期时间60s,这样就没个请求只能请求一次,避免了多次调用的问题 2.6 白名单黑名单 三、防重放和防篡改拦截器 这里我们使用timestampnoncesign对接口进行安全处理 1. 构建请求头 Data Builder public class RequestHeader { /** * 签名 */ private String sign; /** * 时间戳 */ private Long timestamp; /** * 临时的数据 */ private String nonce; } 2. 保存请求流对象 public class SignRequestWrapper extends HttpServletRequestWrapper { //用于将流保存下来 private byte[] requestBody null; public SignRequestWrapper(HttpServletRequest request) throws IOException { super(request); requestBody StreamUtils.copyToByteArray(request.getInputStream()); } Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais new ByteArrayInputStream(requestBody); return new ServletInputStream() { Override public boolean isFinished() { return false; } Override public boolean isReady() { return false; } Override public void setReadListener(ReadListener readListener) { } Override public int read() throws IOException { return bais.read(); } }; } Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } } 3. 创建请求数据处理工具 Slf4j public class HttpDataUtil { /** * post请求处理获取 Body 参数转换为SortedMap * * param request */ public static SortedMapString, String getBodyParams(final HttpServletRequest request) throws IOException { byte[] requestBody StreamUtils.copyToByteArray(request.getInputStream()); String body new String(requestBody); return JsonUtils.parseObject(body, SortedMap.class); } /** * get请求处理将URL请求参数转换成SortedMap */ public static SortedMapString, String getUrlParams(HttpServletRequest request) { String param ; SortedMapString, String result new TreeMap(); if (StringUtils.isEmpty(request.getQueryString())) { return result; } try { param URLDecoder.decode(request.getQueryString(), utf-8); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } String[] params param.split(); for (String s : params) { String[] array s.split(); result.put(array[0], array[1]); } return result; } } 4. 签名验证工具 Slf4j public class SignUtil { /** * 验证签名 * 验证算法把timestamp JsonUtil.object2Json(SortedMap)合成字符串然后MD5 */ SneakyThrows public static boolean verifySign(SortedMapString, String map, RequestHeader requestHeader) { String params requestHeader.getNonce() requestHeader.getTimestamp() JsonUtils.toJsonString(map); return verifySign(params, requestHeader); } /** * 验证签名 */ public static boolean verifySign(String params, RequestHeader requestHeader) { log.debug(客户端签名: {}, requestHeader.getSign()); if (StringUtils.isEmpty(params)) { return false; } log.info(客户端上传内容: {}, params); String paramsSign DigestUtils.md5DigestAsHex(params.getBytes()).toUpperCase(); log.info(客户端上传内容加密后的签名结果: {}, paramsSign); return requestHeader.getSign().equals(paramsSign); } } 5. 创建拦截器SignFilter Slf4j public class SignFilter implements Filter { private static final Long signMaxTime 60L; private static final String NONCE_KEY x-nonce-; Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) servletRequest; log.info(过滤URL:{}, httpRequest.getRequestURI()); //request数据流只能读取一次这里保存request流 HttpServletRequestWrapper requestWrapper new SignRequestWrapper(httpRequest); //构建请求头 String nonceHeader httpRequest.getHeader(X-Nonce); String timeHeader httpRequest.getHeader(X-Time); String signHeader httpRequest.getHeader(X-Sign); //验证请求头是否存在 if (StringUtils.isEmpty(nonceHeader) || ObjectUtils.isEmpty(timeHeader) || StringUtils.isEmpty(signHeader)) { throw new RuntimeException(请求头不存在); } RequestHeader requestHeader RequestHeader.builder() .nonce(httpRequest.getHeader(X-Nonce)) .timestamp(Long.parseLong(httpRequest.getHeader(X-Time))) .sign(httpRequest.getHeader(X-Sign)).build(); /* * 1.验证签名是否过期防止重放 * 判断timestamp时间戳与当前时间是否操过60s过期时间根据业务情况设置,如果超过了就提示签名过期。 */ long now System.currentTimeMillis() / 1000; if (now - requestHeader.getTimestamp() signMaxTime) { throw new RuntimeException(签名过期); } //2. 判断nonce是否重复发送 boolean nonceExists RedisUtils.hasKey(NONCE_KEY requestHeader.getNonce()); if (nonceExists) { //请求重复 throw new RuntimeException(请求重复); } else { RedisUtils.set(NONCE_KEY requestHeader.getNonce(), requestHeader.getNonce(), signMaxTime); } // 3. 验证签名防止篡改 boolean accept; SortedMapString, String paramMap; switch (httpRequest.getMethod()) { case GET: paramMap HttpDataUtil.getUrlParams(requestWrapper); accept SignUtil.verifySign(paramMap, requestHeader); break; case POST: paramMap HttpDataUtil.getBodyParams(requestWrapper); accept SignUtil.verifySign(paramMap, requestHeader); break; default: accept true; break; } if (accept) { filterChain.doFilter(requestWrapper, servletResponse); } else { throw new RuntimeException(签名有误请重新请求); } } } 6. 配置拦截器 Configuration public class SignFilterConfiguration { Bean public FilterRegistrationBean contextFilterRegistrationBean() { FilterRegistrationBean registration new FilterRegistrationBean(); registration.setFilter(new SignFilter()); registration.addUrlPatterns(/sign/*); registration.setName(SignFilter); // 设置过滤器被调用的顺序 registration.setOrder(1); return registration; } } 7. 测试 RequestMapping() RestController public class SignDemoController { PostMapping(/sign/demo1) public R demo1(RequestBody DemoDto demoDto) { System.out.println(执行了demo1); return R.ok(); } GetMapping(/demo2) public R demo2() { System.out.println(执行了demo2); return R.ok(); } } Data class DemoDto { private Integer age; private String username; private Long id; }
http://www.w-s-a.com/news/716495/

相关文章:

  • 安通建设有限公司网站东莞地铁app
  • 群晖nas做网站滨州教育平台 网站建设
  • 住房城市乡建设部网站装修平台有哪些
  • 小米网站 用什么做的深圳广告公司前十强
  • 勤哲网站开发视频瑞安 网站建设培训
  • 有个蓝色章鱼做标志的网站高端的网站建设怎么做
  • 建站网址导航hao123html网页设计实验总结
  • 西宁市网站建设价格丽水集团网站建设
  • 长宁怎么做网站优化好本机怎么放自己做的网站
  • 诚信网站备案中心网站字体怎么设置
  • 企业网站建设费是无形资产吗佛山网站建设哪个好点
  • 网站建设就业方向国开行网站毕业申请怎么做
  • 创建一个网站的费用wordpress 4.0 安装
  • 会员登录系统网站建设dw软件是做什么用的
  • 手机网站被做跳转长沙网上购物超市
  • 网站建设中网站需求分析设计网站推荐html代码
  • 容易收录的网站台州汇客网站建设
  • 企业网站源码百度网盘下载网站备案号如何查询密码
  • 个人网站建设课程宣传栏制作效果图
  • 自己做的网站能上传吗网上做彩票网站排名
  • 教育培训网站模板下载自己做商务网站有什么利弊
  • 平面设计公司网站兰州室内设计公司排名
  • 个人工作室注册条件温州seo结算
  • 360免费建站系统中国建设银行官网站黄金部王毅
  • 罗源福州网站建设个体户可以网站备案吗
  • 网站开发 专有名词pc网站建设和推广
  • 上海部道网站 建设conoha wordpress
  • 手机测评做视频网站宝塔可以做二级域名网站么
  • 代理公司注册济南重庆seo优化效果好
  • 佛山市骏域网站建设专家徐州网站建设价格