1.需求:现在A公司与B公司进行合作,B公司需要调用A公司开放的外网接口获取数据,如何保证外网开放接口的安全性?
2,使用令牌方式
比如支付宝对外提供支付的接口,爱乐生公司需要调用支付宝的接口。在爱乐生调用支付宝接口的时候,支付宝进行过滤器拦截,查看参数中的accessToken信息,是否能在redis缓存中的找到对应的公司,且同时对对方开放。如果没问题,则可以调用接口。
令牌的设计方式一般会设计到以下几个参数:
App_Name 表示机构名称
App_ID 应用id
App_Secret 应用密钥 (可更改)
Is_flag 是否可用 (是否对某个机构开放)
access_token 上一次access_token
3,生成accessToken 的接口:
package com.zfb.api.controller; import java.util.UUID; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.zfb.base.Response; import com.zfb.entity.AppEntity; import com.zfb.mapper.AppMapper; import com.zfb.response.IndexResponse; import com.zfb.utils.BaseRedisService; @Controller public class Index extends Response { @Autowired private BaseRedisService baseRedisService; @Autowired private AppMapper appMapper; private static final long TIMEOUT = 60 * 60 * 60; @RequestMapping("/index") @ResponseBody private String index() { return "index"; } @RequestMapping("/postAccessToken") @ResponseBody private String postAccessToken() { AppEntity appEntity = new AppEntity(); appEntity.setAppId("1QA2was");//不可变 appEntity.setAppName("aiyusheng"); appEntity.setAppSecret("ssss"); appEntity.setId(1); appEntity.setIsFlag(0); getAccessToken(appEntity); return "index"; } /** * 访问获取accessToken appid+appsecret 1,如果找这个机构,说明无权访问 2,如果if_flag为1,说明接口关闭了 * 3,如果找到这个机构,且为0的话,开始生成access_token 3.1,redis 缓存中先删除之前的access_oken * 3.2,创建新的access_token,同时放入到缓存中 * * @return */ @RequestMapping("/getAccessToken") @ResponseBody private String getAccessToken(AppEntity appEntity) { AppEntity findApp = appMapper.findApp(appEntity); // 如果找到这个机构,且为0的话,开始生成access_token IndexResponse response = firstCheck(new IndexResponse(), findApp); if (response.getRtnCode() != 200) { return "fail"; } String accessToken = findApp.getAccessToken(); baseRedisService.delKey(accessToken); String generateAccessToken = generateAccessToken(findApp.getAppId(), findApp.getAppSecret()); //更新mysql 数据库 appMapper.updateAccessToken(generateAccessToken, appEntity.getAppId()); return "success"; } public String generateAccessToken(String appid, String appSecret) { String accessToken = UUID.randomUUID().toString() + "_" + appid + "_" + appSecret; baseRedisService.setString(accessToken, appid, TIMEOUT); return accessToken; } public IndexResponse firstCheck(IndexResponse indexResponse, AppEntity findApp) { if (findApp == null) { indexResponse.setResultError("没有对应的机构"); return null; } if (findApp.getIsFlag() != 0) { indexResponse.setResultError("没有对" + findApp.getAppName() + "开放"); return indexResponse; } // 查询成功 indexResponse.setRtnCode(200); return indexResponse; } }
过滤器:
package com.zfb.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import com.zfb.utils.BaseRedisService; @WebFilter(filterName = "tokenAccessFilter", urlPatterns = "/pay/*") public class TokenAccessFilter implements Filter { @Autowired private BaseRedisService baseRedisService; public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String accessToken = request.getParameter("accessToken"); if (!StringUtils.isEmpty(accessToken)) { //redis 里面的key 是 accessToken value是appid String appid = (String) baseRedisService.getString(accessToken); // 代表没有过期 if (!StringUtils.isEmpty(appid)) { chain.doFilter(request, response); } } } public void destroy() { } }