三方API鉴权指南

API

Posted by Claire on April 9, 2021

此处使用带时间戳的参数加密鉴权方式

身份认证通用

1.1 参数说明

以下为必传参数

序号 参数 类型 说明
1 t string 当前时间戳
2 uid string 用户id
3 sign string 用户参数加密字段
4 priority string 优先级

1.2 返回值说明

序号 code message 说明
1 2003 参数范围错误  
2 2004 用户不存在或者不可用 UID对应用户异常
3 1001 未知错误  
4 1002 系统异常  
5 1003 接口鉴权失败 用户认证失败
6 1004 接口鉴权缺少参数 接口必要参数缺失

1.3 Java Demo

1.3.1 客户端发送

public class demo{
    public String testSendAuth(){
        String uid ="4";
        String password = "somekey";
        try {
            Map<String, Object> parmMap = new HashMap<>();
            parmMap.put("biz", "测试业务");
            parmMap.put("prod", "测试产品");
            parmMap.put("fileid", "randomfileid1");
            parmMap.put("priority", "0");
            parmMap.put("t", String.valueOf(System.currentTimeMillis()));
            String uploadSign = getSignature(uid, password, parmMap);
            parmMap.put("uid", uid);
            parmMap.put("sign", uploadSign);
     
            StopWatch clock = new StopWatch("发送");
            clock.start("postfile");
            String result = HttpUtil.post("http://127.0.0.1:8080/web/test/auth", parmMap);
            clock.stop();
     
            return result;
        }catch (Exception e){
            logger.error("",e);
        }
        return null;
    }
     
     
    public static String getSignature(String uid, String appkey, Map<String, Object> parmMap) {
        List<String> keys = new ArrayList<String>(parmMap.keySet());
        Collections.sort(keys);
        StringBuffer prestr = new StringBuffer(uid);
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            if("uid".equals(key) || "sign".equals(key)){
                continue;
            }
            String value = (String) parmMap.get(key);
            prestr.append(key).append("=").append(value);
        }
        prestr.append(appkey);
        String signature = null;
        signature = DigestUtils.md5Hex(prestr.toString().getBytes(Charset.forName("utf-8"))).toLowerCase();
        return signature;
    }
}

1.3.2 服务端接收,鉴权

   @PostMapping("auth")
  public void authApi(HttpServletRequest request, HttpServletResponse response) throws Exception {
        boolean result = authHelper.authValidate(request, response);
        if(result){
            System.out.println( "success");
        }
        System.out.println("failed");
    }

AuthHelper如下:

@Service("authHelper")
public class AuthHelper {
    private static Logger LOG = LoggerFactory.getLogger(AuthHelper.class);
    private static final String PARAM_T = "t";

    private static final String PARAM_SIGN = "sign";

    private static final String PARAM_UID = "uid";

    public boolean authValidate(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html;charset=utf-8");
        ApiReturnData result = new ApiReturnData();
        try {
            String authTimespan = request.getParameter("t");
            String authSign = request.getParameter("sign");
            String uidstr = request.getParameter("uid");
            String priority = request.getParameter("priority");

            if (StringUtils.isEmpty(authTimespan) || StringUtils.isEmpty(authSign) || StringUtils.isBlank(uidstr)) {
                result.setMsg("接口鉴权缺少参数");
                result.setCode("1004");
                response.getWriter().write(Constant.gson.toJson(result));
                return false;
            }

            long uid = 0L;
            String authAppkey = "";
            try {
                uid = Long.parseLong(uidstr);
                UserInfo userInfo =toGetUserInfo();

                if (null == userInfo || 1 != userInfo.getStatus().intValue()) {
                    result.setMsg("用户不存在或者不可用");
                    result.setCode("2004");
                    response.getWriter().write(Constant.gson.toJson(result));
                    return false;
                }
                if (AccountTypeEnum.API.getValue() != userInfo.getAccounttype().intValue()) {
                    result.setMsg("用户类型不正确");
                    result.setCode("2012");
                    response.getWriter().write(Constant.gson.toJson(result));
                    return false;
                }

                authAppkey = userInfo.getAppkey();
            } catch (Exception e) {
                result.setMsg("用户不存在或者不可用");
                result.setCode("2004");
                response.getWriter().write(Constant.gson.toJson(result));
                return false;
            }

            Map<String, String[]> params = request.getParameterMap();
            List<String> keys = new ArrayList<>();
            keys.addAll(params.keySet());

            Collections.sort(keys);

            //主要验签的实现
            if (!checkMD5(uidstr, authAppkey, keys, params, authSign)) {
                result.setMsg("接口鉴权失败");
                result.setCode("1003");
                response.getWriter().write(Constant.gson.toJson(result));
                return false;
            }
        } catch (Exception e) {
            LOG.error("", e);
            result.setMsg("未知错误");
            result.setCode("1001");
            response.getWriter().write(Constant.gson.toJson(result));
            return false;
        }
        return true;
    }


    private boolean checkMD5(String uidstr, String auth_appkey, List<String> keys, Map<String, String[]> params, String auth_sign) {
        boolean result = true;
        StringBuffer data = new StringBuffer(uidstr);
        for (String key : keys) {
            if ("uid".equals(key) || "sign".equals(key)) {
                continue;
            }
            data.append(key).append("=").append(((String[]) params.get(key))[0]);
        }
        data.append(auth_appkey);
        String md5 = "";
        try {
            md5 = DigestUtils.md5Hex(data.toString().getBytes("UTF-8")).toLowerCase();
        } catch (UnsupportedEncodingException unsupportedEncodingException) {
        }
        LOG.debug("request data" + data + ",md5:" + md5 + ",sign:" + auth_sign);
        if (md5.equals(auth_sign)) {
            result = true;
        } else {
            result = false;
        }
        return result;
    }
}