java Authorization HMAC-SHA256 OAuth2.0身份认证接口访问

项目已经正常跑的代码

常量定义

/**
 * NS全局常量定义
 *
 * @author zhangbs
 * @version 2021-05-28
 */
public class NsConstant {
    public final static String URL = "xxxx";
    public final static String REALM = "xxx";
    public final static String ACCESS_TOKEN = "xxx";
    public final static String TOKEN_SECRET = "xxx";
    public final static String CONSUMER_KEY = "xxx";
    public final static String CONSUMER_SECRET = "xxx";
    public final static String SUCCESS_OK = "200";
}

请求工具类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import xxx.MapUtils;
import xxx.DateUtils;
import xxx.StringUtils;
import xxx.NsAuthInfo;
import xxx.EipDateUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * NS请求工具类
 *
 * @author zhangbs
 * @version 2021-05-28
 */
public class NsRequestUtils {


    /**
     * 发送请求并返回响应结果
     *
     * @param url           请求url
     * @param requestMethod 请求方式
     * @param paramsMap     参数
     * @param authInfo      认证信息
     * @return 请求响应结果
     */
    public static Map<String, Object> executeRequest(String url, String requestMethod, Map<String, Object> paramsMap, NsAuthInfo authInfo) {
        Map<String, Object> resultMap = MapUtils.newHashMap();
        try {
            String authorization = NsRequestUtils.constructAuthHeader(authInfo, requestMethod);

            CloseableHttpClient httpClient = HttpClientBuilder.create().build();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Accept", "*/*");
            httpPost.setHeader("Authorization", authorization);

            String jsonParams = JSON.toJSONString(paramsMap);
            HttpEntity entityParam = new StringEntity(jsonParams, ContentType.create("application/json", "UTF-8"));
            httpPost.setEntity(entityParam);
            HttpResponse response = httpClient.execute(httpPost);

            // 状态码
            resultMap.put("code", response.getStatusLine().getStatusCode() + "");
            // 返回结果
            resultMap.put("result", EntityUtils.toString(response.getEntity(), "utf-8"));
        } catch (Exception e) {
            resultMap.put("code", "400");
        }

        return resultMap;
    }

    /**
     * 生成签名并组合Authorization头
     * 如"/", 编码后为: %2F
     *
     * @return 编码后的字符串
     */
    public static String constructAuthHeader(NsAuthInfo auth, String method) throws Exception {
        // 基础信息
        String url = auth.getUrl();
        // 时间戳
        long timestamp = new Date().getTime() / 1000;
        // 转成大写
        method = method.toUpperCase();
        // 签名方法
        String signatureMethod = "HMAC-SHA256", signatureMethodCode = "HmacSHA256";
        // 基础信息
        String accessToken = auth.getAccessToken(), tokenSecret = auth.getTokenSecret(),
                consumerKey = auth.getConsumerKey(), consumerSecret = auth.getConsumerSecret(),
                realm = auth.getRealm(), nonce = StringUtils.getRandomStr(32);
        // 组合Key
        String key = consumerSecret + '&' + tokenSecret;
        // 截取问号前的URL
        String encodeURL = url.split("\\?")[0];

        // 获取URL参数
        Map<String, String> parameters = urlSplit(url);
        parameters.put("oauth_consumer_key", consumerKey);
        parameters.put("oauth_nonce", nonce);
        parameters.put("oauth_signature_method", signatureMethod);
        parameters.put("oauth_timestamp", String.valueOf(timestamp));
        parameters.put("oauth_token", accessToken);
        parameters.put("oauth_version", "1.0");
        String parameterString = sortAndConcat(parameters);
        // 组合待签字符串
        StringBuilder signatureBaseString = new StringBuilder(100);
        signatureBaseString.append(method.toUpperCase());
        signatureBaseString.append('&');
        signatureBaseString.append(urlEncode(encodeURL));
        signatureBaseString.append('&');
        signatureBaseString.append(urlEncode(parameterString));
        // 转换成String类型
        String signatureString = signatureBaseString.toString();
        // 生成签名
        byte[] bytesToSign = signatureString.getBytes("UTF-8");
        byte[] keyBytes = key.getBytes("UTF-8");
        SecretKeySpec signingKey = new SecretKeySpec(keyBytes, signatureMethodCode);
        Mac mac = Mac.getInstance(signatureMethodCode);
        mac.init(signingKey);
        byte[] signedBytes = mac.doFinal(bytesToSign);
        String signature = urlEncode(new String(Base64.encodeBase64(signedBytes, false)));

        return new StringBuilder().append("OAuth ")
                .append("realm").append("=\"").append(realm)
                .append("\",").append("oauth_consumer_key").append("=\"").append(consumerKey)
                .append("\",").append("oauth_token").append("=\"").append(accessToken)
                .append("\",").append("oauth_signature_method").append("=\"").append(signatureMethod)
                .append("\",").append("oauth_timestamp").append("=\"").append(timestamp)
                .append("\",").append("oauth_nonce").append("=\"").append(nonce)
                .append("\",").append("oauth_version").append("=\"").append("1.0")
                .append("\",").append("oauth_signature").append("=\"").append(signature)
                .append("\"").toString();
    }


    /**
     * 返回参数double的空处理
     *
     * @param jsonObject json对象
     * @param key
     * @return
     */
    public static Double killNullDouble(JSONObject jsonObject, String key) {
        Double result = jsonObject.getDouble(key);
        return result == null ? 0.0D : result;
    }

    /**
     * 获取加上指定月份的开始日期 格式yyyy/MM/dd
     *
     * @param month
     * @return
     */
    public static String getStartDate(int month, String append) {
        Date monthAdd = DateUtils.addMonths(new Date(), month);
        String yearMonth = DateUtils.formatDate(monthAdd, "yyyy/MM");
        return yearMonth + append;
    }

    /**
     * 获取加上指定月份的结束日期 格式yyyy/MM/dd
     *
     * @param month
     * @return
     */
    public static String getEndDate(int month) {
        if (month < 0) {
            Date monthAdd = DateUtils.addMonths(new Date(), month);
            String yearMonth = DateUtils.formatDate(monthAdd, "yyyy/MM");
            return yearMonth + "/" + EipDateUtils.getMonthHasDays(monthAdd);
        } else {
            return DateUtils.formatDate(new Date(), "yyyy/MM/dd");
        }
    }

    /**
     * 解析出url参数中的键值对
     * 如 "restlet.nl?script=248&deploy=1",解析出script:24,deploy:1存入map中
     *
     * @param URL url地址
     * @return url请求参数部分
     */
    public static Map<String, String> urlSplit(String URL) {
        Map<String, String> mapRequest = new HashMap<String, String>();
        String[] arrSplit = null;
        String strUrlParam = TruncateUrlPage(URL);
        if (strUrlParam == null) {
            return mapRequest;
        }
        arrSplit = strUrlParam.split("[&]");
        for (String strSplit : arrSplit) {
            String[] arrSplitEqual = null;
            arrSplitEqual = strSplit.split("[=]");
            //解析出键值
            if (arrSplitEqual.length > 1) {
                //正确解析
                mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
            } else {
                if (arrSplitEqual[0] != "") {
                    //只有参数没有值,不加入
                    mapRequest.put(arrSplitEqual[0], "");
                }
            }
        }
        return mapRequest;
    }

    /**
     * 去掉url中的路径,留下请求参数部分
     *
     * @param strURL url地址
     * @return url请求参数部分
     */
    private static String TruncateUrlPage(String strURL) {
        String strAllParam = null;
        String[] arrSplit = null;
        strURL = strURL.trim().toLowerCase();
        arrSplit = strURL.split("[?]");
        if (strURL.length() > 1) {
            if (arrSplit.length > 1) {
                for (int i = 1; i < arrSplit.length; i++) {
                    strAllParam = arrSplit[i];
                }
            }
        }
        return strAllParam;
    }


    /**
     * 对URL参数进行排序
     * 如"script:248,deploy:1", 排序后deploy=1&script=248
     *
     * @param parameters 参数的键值对
     * @return 排序后的字符串
     */
    private static String sortAndConcat(Map<String, String> parameters) {
        StringBuilder encodedParams = new StringBuilder(100);
        Object[] arr = parameters.keySet().toArray();
        Arrays.sort(arr);
        for (Object key : arr) {
            if (encodedParams.length() > 0) {
                encodedParams.append('&');
            }
            encodedParams.append(key).append('=').append(parameters.get(key));
        }
        return encodedParams.toString();
    }

    /**
     * 对字符串进行URL编码
     * 如"/", 编码后为: %2F
     *
     * @param str 传入字符串
     * @return 编码后的字符串
     */
    private static String urlEncode(String str) {
        try {
            return URLEncoder.encode(str, "UTF-8")
                    .replace("+", "%20")
                    .replace("*", "%2A")
                    .replace("%7E", "~");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
    }

认证参数信息


/**
 * NS认证信息
 *
 * @author zhangbs
 * @version 2021-05-28
 */
public class NsAuthInfo {

    public NsAuthInfo(String realm, String url, String accessToken, String tokenSecret, String consumerKey, String consumerSecret) {
        setRealm(realm);
        setUrl(url);
        setAccessToken(accessToken);
        setTokenSecret(tokenSecret);
        setConsumerKey(consumerKey);
        setConsumerSecret(consumerSecret);
    }

    private String url;
    private String accessToken;
    private String tokenSecret;
    private String consumerKey;
    private String consumerSecret;
    private String realm;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public String getTokenSecret() {
        return tokenSecret;
    }

    public void setTokenSecret(String tokenSecret) {
        this.tokenSecret = tokenSecret;
    }

    public String getConsumerKey() {
        return consumerKey;
    }

    public void setConsumerKey(String consumerKey) {
        this.consumerKey = consumerKey;
    }

    public String getConsumerSecret() {
        return consumerSecret;
    }

    public void setConsumerSecret(String consumerSecret) {
        this.consumerSecret = consumerSecret;
    }

    public String getRealm() {
        return realm;
    }

    public void setRealm(String realm) {
        this.realm = realm;
    }

请求参考

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import xxx.NsAuthInfo;
import xxx.NsConstant;
import xxx.NsRequestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
    /**
     * 执行定时任务(默认跑昨天至今天的数据)
     */
    public void execute(String systemCode, String date) {
        // 参数放置
        Map<String, Object> paramsMap = MapUtils.newHashMap();
        String startDate = StringUtils.isNotEmpty(date) ? date : DateUtils.formatDate(DateUtils.addDays(new Date(), -1), "yyyy/MM/dd");
        String endDate = StringUtils.isNotEmpty(date) ? date : DateUtils.formatDate(DateUtils.addDays(new Date(), -0), "yyyy/MM/dd");

        paramsMap.put("startDate", startDate);
        paramsMap.put("endtDate", endDate);
        paramsMap.put("subsidiary", systemCode);

        String url = NsConstant.URL + "&script=701";
        // 构建认证信息
        NsAuthInfo authInfo = new NsAuthInfo(NsConstant.REALM, url, NsConstant.ACCESS_TOKEN, NsConstant.TOKEN_SECRET,
                NsConstant.CONSUMER_KEY, NsConstant.CONSUMER_SECRET);

        Map<String, Object> result = NsRequestUtils.executeRequest(url, "POST", paramsMap, authInfo);

        // 构建保存信息
        if (NsConstant.SUCCESS_OK.equals(result.get("code"))) {
            // 做业务处理
        }
    }

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容