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() { } }