对外开放的接口验证方式

接口安全问题

    请求身份是否合法?
    请求参数是否被篡改?
    请求是否唯一?

AccessKey&SecretKey (开放平台)
请求身份

为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。
防止篡改

参数签名

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

请求携带参数AccessKey和Sign,只有拥有合法的身份AccessKey和正确的签名Sign才能放行。这样就解决了身份验证和参数篡改问题,即使请求参数被劫持,由于获取不到SecretKey(仅作本地加密使用,不参与网络传输),无法伪造合法的请求。
重放攻击

虽然解决了请求参数被篡改的隐患,但是还存在着重复使用请求参数伪造二次请求的隐患。

timestamp+nonce方案

nonce指唯一的随机字符串,用来标识每个被签名的请求。通过为每个请求提供一个唯一的标识符,服务器能够防止请求被多次使用(记录所有用过的nonce以阻止它们被二次使用)。

然而,对服务器来说永久存储所有接收到的nonce的代价是非常大的。可以使用timestamp来优化nonce的存储。

假设允许客户端和服务端最多能存在15分钟的时间差,同时追踪记录在服务端的nonce集合。当有新的请求进入时,首先检查携带的timestamp是否在15分钟内,如超出时间范围,则拒绝,然后查询携带的nonce,如存在已有集合,则拒绝。否则,记录该nonce,并删除集合内时间戳大于15分钟的nonce(可以使用redis的expire,新增nonce的同时设置它的超时失效时间为15分钟)。
实现

请求接口:http://api.test.com/test?name=hello&home=world&work=java

    客户端
        生成当前时间戳timestamp=now和唯一随机字符串nonce=random
        按照请求参数名的字母升序排列非空请求参数(包含AccessKey)
        stringA="AccessKey=access&home=world&name=hello&work=java×tamp=now&nonce=random";
        拼接密钥SecretKey
        stringSignTemp="AccessKey=access&home=world&name=hello&work=java×tamp=now&nonce=random&SecretKey=secret";
        MD5并转换为大写
        sign=MD5(stringSignTemp).toUpperCase();
        最终请求
        http://api.test.com/test?name=hello&home=world&work=java×tamp=now&nonce=nonce&sign=sign;

    服务端


   

Token&AppKey(APP)

在APP开放API接口的设计中,由于大多数接口涉及到用户的个人信息以及产品的敏感数据,所以要对这些接口进行身份验证,为了安全起见让用户暴露的明文密码次数越少越好,然而客户端与服务器的交互在请求之间是无状态的,也就是说,当涉及到用户状态时,每次请求都要带上身份验证信息。
Token身份验证

    用户登录向服务器提供认证信息(如账号和密码),服务器验证成功后返回Token给客户端;
    客户端将Token保存在本地,后续发起请求时,携带此Token;
    服务器检查Token的有效性,有效则放行,无效(Token错误或过期)则拒绝。

安全隐患:Token被劫持,伪造请求和篡改参数。
Token+AppKey签名验证

与上面开发平台的验证方式类似,为客户端分配AppKey(密钥,用于接口加密,不参与传输),将AppKey和所有请求参数组合成源串,根据签名算法生成签名值,发送请求时将签名值一起发送给服务器验证。这样,即使Token被劫持,对方不知道AppKey和签名算法,就无法伪造请求和篡改参数。再结合上述的重发攻击解决方案,即使请求参数被劫持也无法伪造二次重复请求。
实现
登陆和退出请求


后续请求

    客户端
    和上述开放平台的客户端行为类似,把AccessKey改为token即可。

    服务端


   

转载至:https://blog.youkuaiyun.com/qq_18495465/article/details/79248608

 
 
 
### Spring Boot 配置并暴露 RESTful API 对外接口 在 Spring Boot 中,可以通过定义控制器类(Controller),结合注解的方式快速开发和暴露 RESTful API。以下是具体实现方式: #### 定义 Controller 类 Spring Boot 使用 `@RestController` 注解来标记一个类作为 REST 控制器。该注解是一个专门用于构建 RESTful Web 服务的简化版 `@Controller`。 ```java @RestController @RequestMapping("/api/users") // 统一前缀路径 public class UserController { @GetMapping("/{id}") // 映射 GET 请求到指定 URL 路径 public ResponseEntity<User> getUserById(@PathVariable Long id) { User user = userService.findById(id); // 假设有一个 UserService 获取用户信息 if (user != null) { return ResponseEntity.ok(user); } else { return ResponseEntity.notFound().build(); } } @PostMapping("/") // 映射 POST 请求到指定 URL 路径 public ResponseEntity<Void> createUser(@RequestBody User newUser) { userService.save(newUser); // 假设有保存用户的逻辑 return ResponseEntity.status(HttpStatus.CREATED).build(); } @PutMapping("/{id}") // 映射 PUT 请求更新资源 public ResponseEntity<Void> updateUser(@PathVariable Long id, @RequestBody User updatedUser) { boolean isUpdated = userService.update(id, updatedUser); // 更新逻辑 if (isUpdated) { return ResponseEntity.noContent().build(); } else { return ResponseEntity.notFound().build(); } } @DeleteMapping("/{id}") // 映射 DELETE 请求删除资源 public ResponseEntity<Void> deleteUser(@PathVariable Long id) { boolean isDeleted = userService.delete(id); // 删除逻辑 if (isDeleted) { return ResponseEntity.noContent().build(); } else { return ResponseEntity.notFound().build(); } } } ``` 上述代码展示了如何通过不同类型的 HTTP 方法映射请求,并返回相应的响应状态码[^1]。 #### 处理 JSON 数据 为了使应用程序能够自动解析和序列化 JSON 数据,可以依赖 Jackson 库(默认集成于 Spring Boot)。当客户端发送带有 JSON 的请求时,Spring 自动将其转换为 Java 对象;反之亦然。 例如,在上面的例子中,`@RequestBody` 将传入的 JSON 数据绑定到 `User` 实体对象上,而 `ResponseEntity<User>` 则负责将结果转化为 JSON 返回给调用方[^2]。 #### 配置跨域支持 如果需要让外部应用访问您的 API,则可能涉及 CORS(Cross-Origin Resource Sharing)设置。可以在全局范围内启用 CORS 支持或者针对单个端点单独配置。 ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 允许所有路径下的请求 .allowedOrigins("*") // 允许任何域名发起请求 .allowedMethods("GET", "POST", "PUT", "DELETE"); // 指定允许的方法类型 } } ``` 此片段说明了如何通过编程方式开启 CORS 功能以便其他源能安全地消费这些公开的服务[^3]。 #### 测试 API 接口 最后一步是对所创建好的 RESTful APIs 进行测试验证其功能是否正常工作。Postman 或者 curl 工具都是不错的选择来进行手动调试;而对于自动化单元/集成测试来说,JUnit 结合 MockMvc 提供了一套强大的解决方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值