API开放平台接口设计-------令牌方式

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

    }

}

 

posted @ 2019-07-30 15:23  Chris,Cai  阅读(2515)  评论(0编辑  收藏  举报