常用解决办法
- 使用加签名方式,防止篡改数据
- 使用Https加密传输
- 搭建OAuth2.0认证授权
- 使用令牌方式
- 搭建网关实现黑名单和白名单
令牌方式保证接口安全
- 表设计
CREATE TABLE `table_app` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`app_name` varchar(255) NOT NULL COMMENT '三方系统的名称',
`app_id` varchar(0) NOT NULL COMMENT '应用id',
`app_secrect` varchar(255) NOT NULL COMMENT '应用秘钥(可更改)',
`is_deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否可用',
`last_access_token` varchar(0) NOT NULL DEFAULT '' COMMENT '上一次的access_token',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 代码实现
package com.example.nginx.controller;
import com.example.nginx.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AppController {
@Autowired
private AppService appService;
@GetMapping(path = "/getAccessToken")
public String getAccessToken(String appId, String appSecrect) {
return appService.doGetAccessToken(appId, appSecrect);
}
@GetMapping(path = "/openApi/getResult")
public String getResult() {
return "success";
}
}
@Service
@Transactional(rollbackFor = Exception.class)
public class AppServiceImpl extends ServiceImpl<AppMapper, App> implements AppService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public String doGetAccessToken(String appId, String appSecrect) {
App app = this.getApp(appId);
stringRedisTemplate.delete(app.getLastAccessToken());
String token = TokenUtils.getToken();
app.setLastAccessToken(token);
super.updateById(app);
stringRedisTemplate.opsForValue().set(token, app.getAppId(), 2, TimeUnit.HOURS);
return token;
}
private App getApp(String appId) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("app_id", appId);
App app = super.getOne(queryWrapper);
Assert.notNull(app, "该应用不存在或无访问权限");
return app;
}
}
package com.example.nginx.aop;
import com.example.nginx.util.AopUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Configuration
public class AccessTokenInterceptor extends HandlerInterceptorAdapter {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String accessToken = request.getParameter("accessToken");
if(StringUtils.isEmpty(accessToken)){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
AopUtils.returnMsg("accessToken不能为空", attributes);
return false;
}
String value = stringRedisTemplate.opsForValue().get(accessToken);
if(StringUtils.isEmpty(value)){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
AopUtils.returnMsg("accessToken不存在或失效", attributes);
return false;
}
return true;
}
}
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
@Autowired
private AccessTokenInterceptor accessTokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(accessTokenInterceptor).addPathPatterns("/openApi/**");
}
}
public class AopUtils {
public static void returnMsg(String msg, ServletRequestAttributes attributes) {
HttpServletResponse httpServletResponse = attributes.getResponse();
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
try (PrintWriter servletOutputStream = httpServletResponse.getWriter();) {
Map<String, String> result = new HashMap<String, String>() {
{
put("msg", msg);
}
};
servletOutputStream.print(JSON.toJSONString(result));
servletOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 测试用例
![在这里插入图片描述](https://img-blog.csdnimg.cn/201911040006343.png)
![](https://img-blog.csdnimg.cn/20191104000643124.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191104000653263.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191104000718901.png)
- 遇到的问题
- 拦截器路径配置规则.
一个*:只匹配字符,不匹配路径(/)
两个**:匹配字符,和路径(/)