互聯網API開放平臺安全設計(三)--API安全接口安全設計

互聯網開放平臺設計

1.需求:現在A公司與B公司進行合作,B公司需要調用A公司開放的外網接口獲取數據,

如何保證外網開放接口的安全性。

2.常用解決辦法:

2.1 使用加簽名方式,防止篡改數據

2.2 使用Https加密傳輸

2.3 搭建OAuth2.0認證授權

2.4 使用令牌方式

2.5 搭建網關實現黑名單和白名單

使用令牌方式搭建搭建API開放平臺

原理:爲每個合作機構創建對應的appid、app_secret,生成對應的access_token(有效期2小時),在調用外網開放接口的時候,必須傳遞有效的access_token。

數據庫表設計

CREATE TABLE `m_app` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `app_name` varchar(255) DEFAULT NULL,

  `app_id` varchar(255) DEFAULT NULL,

  `app_secret` varchar(255) DEFAULT NULL,

  `is_flag` varchar(255) DEFAULT NULL,

  `access_token` varchar(255) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

 

App_Name       表示機構名稱

App_ID          應用id

App_Secret      應用密鑰  (可更改)

Is_flag           是否可用 (是否對某個機構開放)

access_token  上一次access_token

獲取AccessToken

 

// 創建獲取getAccessToken
@RestController
@RequestMapping(value = "/auth")
public class AuthController extends BaseApiService {
	@Autowired
	private BaseRedisService baseRedisService;
	private long timeToken = 60 * 60 * 2;
	@Autowired
	private AppMapper appMapper;

	// 使用appId+appSecret 生成AccessToke
	@RequestMapping("/getAccessToken")
	public ResponseBase getAccessToken(AppEntity appEntity) {
		AppEntity appResult = appMapper.findApp(appEntity);
		if (appResult == null) {
			return setResultError("沒有對應機構的認證信息");
		}
		int isFlag = appResult.getIsFlag();
		if (isFlag == 1) {
			return setResultError("您現在沒有權限生成對應的AccessToken");
		}
		// ### 獲取新的accessToken 之前刪除之前老的accessToken
		// 從redis中刪除之前的accessToken
		String accessToken = appResult.getAccessToken();
		baseRedisService.delKey(accessToken);
		// 生成的新的accessToken
		String newAccessToken = newAccessToken(appResult.getAppId());
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("accessToken", newAccessToken);
		return setResultSuccessData(jsonObject);
	}

	private String newAccessToken(String appId) {
		// 使用appid+appsecret 生成對應的AccessToken 保存兩個小時
		String accessToken = TokenUtils.getAccessToken();
		// 保證在同一個事物redis 事物中
		// 生成最新的token key爲accessToken value 爲 appid
		baseRedisService.setString(accessToken, appId, timeToken);
		// 表中保存當前accessToken
		appMapper.updateAccessToken(accessToken, appId);
		return accessToken;
	}
}

編寫攔截器攔截請求,驗證accessToken

//驗證AccessToken 是否正確
@Component
public class AccessTokenInterceptor extends BaseApiService implements HandlerInterceptor {
	@Autowired
	private BaseRedisService baseRedisService;

	/**
	 * 進入controller層之前攔截請求
	 * 
	 * @param httpServletRequest
	 * @param httpServletResponse
	 * @param o
	 * @return
	 * @throws Exception
	 */

	public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o)
			throws Exception {
		System.out.println("---------------------開始進入請求地址攔截----------------------------");
		String accessToken = httpServletRequest.getParameter("accessToken");
		// 判斷accessToken是否空
		if (StringUtils.isEmpty(accessToken)) {
			// 參數Token accessToken
			resultError(" this is parameter accessToken null ", httpServletResponse);
			return false;
		}
		String appId = (String) baseRedisService.getString(accessToken);
		if (StringUtils.isEmpty(appId)) {
			// accessToken 已經失效!
			resultError(" this is  accessToken Invalid ", httpServletResponse);
			return false;
		}
		// 正常執行業務邏輯...
		return true;

	}

	public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o,
			ModelAndView modelAndView) throws Exception {
		System.out.println("--------------處理請求完成後視圖渲染之前的處理操作---------------");
	}

	public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
			Object o, Exception e) throws Exception {
		System.out.println("---------------視圖渲染之後的操作-------------------------0");
	}

	// 返回錯誤提示
	public void resultError(String errorMsg, HttpServletResponse httpServletResponse) throws IOException {
		PrintWriter printWriter = httpServletResponse.getWriter();
		printWriter.write(new JSONObject().toJSONString(setResultError(errorMsg)));
	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章