Twitter 第三方登陆校验

@Value("${app.twitter.login.consumer-key}")
private String consumerKey;
@Value("${app.twitter.login.consumer-secret}")
private String consumerSecret;

private static final String verifyCredentialsUrl = "https://api.twitter.com/1.1/account/verify_credentials.json";
private final Logger log = LoggerFactory.getLogger(this.getClass());
private static final String PREAMBLE = "OAuth";
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
private static final String HMAC_SHA1 = "HmacSHA1";

@Autowired
private AccountManager accountManager;
@Autowired
private UserForbiddenManager userForbiddenManager;
@Autowired
private SmsService smsService;


@Override
public AccountThirdBO process(LoginRequest req) {
    if (StringUtils.isEmpty(req.getAccessToken())
            || StringUtils.isEmpty(req.getSecretToken())
            || StringUtils.isEmpty(req.getThirdId())) {
        throw new BusinessException(ResultEnum.PARA_ERR);
    }
    String provider = AccountConstant.ProviderEnum.twitter.toString();

    String thirdId = getTwitterUnionId(req.getThirdId(), req.getAccessToken(), req.getSecretToken());

    AccountIndex accountIndex = accountManager.getAccountIndex(provider, thirdId);
    boolean unregistered = accountIndex == null;
    if (!unregistered) {
        accountManager.checkPhoneValidation(accountIndex.getUid());
    }

    List<ThirdInfo> thirdInfoList = new ArrayList<>();
    thirdInfoList.add(new ThirdInfo(provider, thirdId, thirdId, ""));

    return new AccountThirdBO(thirdInfoList,
            accountIndex == null ? null : accountIndex.getUid(),
            unregistered,
            false,
            unregistered);
}


private String getTwitterUnionId(String userId, String accessToken, String secretToken) {

    if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(secretToken)) {
        throw new BusinessException(ResultEnum.PARA_ERR);
    }
    HashMap<String, String> headers = new HashMap<String, String>();
    //应用口令

    Map<String, String> queryParams = new HashMap<>();
    queryParams.put("user_id", userId);
    queryParams.put("include_entities", Boolean.toString(true));
    Map<String, String> oauthParams = buildOauthParams();
    oauthParams.put("oauth_token", accessToken);
    Map<String, String> params = new HashMap<>(oauthParams);
    params.putAll(queryParams);
    oauthParams.put("oauth_signature", generateTwitterSignature(params, "GET", verifyCredentialsUrl, consumerSecret, secretToken));
    String header = buildHeader(oauthParams);

    headers.put("Authorization", header);
    String result = HttpInvokeUtil.httpGetWithHeader(verifyCredentialsUrl, queryParams, headers);
    log.info("getTwitterUnionId result:{}", result);
    JSONObject jsonObject = JSON.parseObject(result);
    return jsonObject.get("id_str").toString();

}

public static String generateTwitterSignature(Map<String, String> params, String method, String baseUrl, String apiSecret, String tokenSecret) {
    TreeMap<String, String> map = new TreeMap<>(params);
    String str = parseMapToString(map, true);
    String baseStr = method.toUpperCase() + "&" + URLEncoder.encode(baseUrl) + "&" + URLEncoder.encode(str);
    String signKey = apiSecret + "&" + (StringUtils.isEmpty(tokenSecret) ? "" : tokenSecret);
    byte[] signature = sign(signKey.getBytes(DEFAULT_ENCODING), baseStr.getBytes(DEFAULT_ENCODING), HMAC_SHA1);

    return new String(Base64Utils.encode(signature, false));
}

public static String parseMapToString(Map<String, String> params, boolean encode) {
    if (null == params || params.isEmpty()) {
        return "";
    }
    List<String> paramList = new ArrayList<>();
    params.forEach((k, v) -> {
        if (null == v) {
            paramList.add(k + "=");
        } else {
            paramList.add(k + "=" + (encode ? URLEncoder.encode(v) : v));
        }
    });
    return String.join("&", paramList);
}

private static byte[] sign(byte[] key, byte[] data, String algorithm) {
    try {
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data);
    } catch (NoSuchAlgorithmException ex) {
        throw new BusinessException(ResultEnum.PARA_ERR);
    } catch (InvalidKeyException ex) {
        throw new BusinessException(ResultEnum.PARA_ERR);
    }
}



private Map<String, String> buildOauthParams() {
    Map<String, String> params = new HashMap<>(5);
    params.put("oauth_consumer_key", consumerKey);
    params.put("oauth_nonce", WXPayUtil.generateNonceStr());
    params.put("oauth_signature_method", "HMAC-SHA1");
    params.put("oauth_timestamp", System.currentTimeMillis()/1000 + "");
    params.put("oauth_version", "1.0");
    return params;
}

private String buildHeader(Map<String, String> oauthParams) {
    final StringBuilder sb = new StringBuilder(PREAMBLE + " ");

    for (Map.Entry<String, String> param : oauthParams.entrySet()) {
        sb.append(param.getKey()).append("=\"").append(URLEncoder.encode(param.getValue())).append('"').append(", ");
    }

    return sb.deleteCharAt(sb.length() - 2).toString();
}

 

 

相关工具类 

public class Base64Utils {

    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
    /**
     * 标准编码表
     */
    private static final byte[] STANDARD_ENCODE_TABLE = { //
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', //
            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', //
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', //
            'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', //
            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', //
            'o', 'p', 'q', 'r', 's', 't', 'u', 'v', //
            'w', 'x', 'y', 'z', '0', '1', '2', '3', //
            '4', '5', '6', '7', '8', '9', '+', '/' //
    };
    /**
     * URL安全的编码表,将 + 和 / 替换为 - 和 _
     */
    private static final byte[] URL_SAFE_ENCODE_TABLE = { //
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', //
            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', //
            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', //
            'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', //
            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', //
            'o', 'p', 'q', 'r', 's', 't', 'u', 'v', //
            'w', 'x', 'y', 'z', '0', '1', '2', '3', //
            '4', '5', '6', '7', '8', '9', '-', '_' //
    };

    // -------------------------------------------------------------------- encode

    /**
     * 编码为Base64,非URL安全的
     *
     * @param arr     被编码的数组
     * @param lineSep 在76个char之后是CRLF还是EOF
     * @return 编码后的bytes
     */
    public static byte[] encode(byte[] arr, boolean lineSep) {
        return encode(arr, lineSep, false);
    }

    /**
     * 编码为Base64,URL安全的
     *
     * @param arr     被编码的数组
     * @param lineSep 在76个char之后是CRLF还是EOF
     * @return 编码后的bytes
     * @since 3.0.6
     */
    public static byte[] encodeUrlSafe(byte[] arr, boolean lineSep) {
        return encode(arr, lineSep, true);
    }

    /**
     * base64编码
     *
     * @param source 被编码的base64字符串
     * @return 被加密后的字符串
     */
    public static String encode(CharSequence source) {
        return encode(source, DEFAULT_CHARSET);
    }

    /**
     * base64编码,URL安全
     *
     * @param source 被编码的base64字符串
     * @return 被加密后的字符串
     * @since 3.0.6
     */
    public static String encodeUrlSafe(CharSequence source) {
        return encodeUrlSafe(source, DEFAULT_CHARSET);
    }

    /**
     * base64编码
     *
     * @param source  被编码的base64字符串
     * @param charset 字符集
     * @return 被加密后的字符串
     */
    public static String encode(CharSequence source, Charset charset) {
        return encode(StringUtils.bytes(source, charset));
    }

    /**
     * base64编码,URL安全的
     *
     * @param source  被编码的base64字符串
     * @param charset 字符集
     * @return 被加密后的字符串
     * @since 3.0.6
     */
    public static String encodeUrlSafe(CharSequence source, Charset charset) {
        return encodeUrlSafe(StringUtils.bytes(source, charset));
    }

    /**
     * base64编码
     *
     * @param source 被编码的base64字符串
     * @return 被加密后的字符串
     */
    public static String encode(byte[] source) {
        return StringUtils.str(encode(source, false), DEFAULT_CHARSET);
    }

    /**
     * base64编码,URL安全的
     *
     * @param source 被编码的base64字符串
     * @return 被加密后的字符串
     * @since 3.0.6
     */
    public static String encodeUrlSafe(byte[] source) {
        return StringUtils.str(encodeUrlSafe(source, false), DEFAULT_CHARSET);
    }

    /**
     * 编码为Base64<br>
     * 如果isMultiLine为<code>true</code>,则每76个字符一个换行符,否则在一行显示
     *
     * @param arr         被编码的数组
     * @param isMultiLine 在76个char之后是CRLF还是EOF
     * @param isUrlSafe   是否使用URL安全字符,一般为<code>false</code>
     * @return 编码后的bytes
     */
    public static byte[] encode(byte[] arr, boolean isMultiLine, boolean isUrlSafe) {
        if (null == arr) {
            return null;
        }

        int len = arr.length;
        if (len == 0) {
            return new byte[0];
        }

        int evenlen = (len / 3) * 3;
        int cnt = ((len - 1) / 3 + 1) << 2;
        int destlen = cnt + (isMultiLine ? (cnt - 1) / 76 << 1 : 0);
        byte[] dest = new byte[destlen];

        byte[] encodeTable = isUrlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;

        for (int s = 0, d = 0, cc = 0; s < evenlen; ) {
            int i = (arr[s++] & 0xff) << 16 | (arr[s++] & 0xff) << 8 | (arr[s++] & 0xff);

            dest[d++] = encodeTable[(i >>> 18) & 0x3f];
            dest[d++] = encodeTable[(i >>> 12) & 0x3f];
            dest[d++] = encodeTable[(i >>> 6) & 0x3f];
            dest[d++] = encodeTable[i & 0x3f];

            if (isMultiLine && ++cc == 19 && d < destlen - 2) {
                dest[d++] = '\r';
                dest[d++] = '\n';
                cc = 0;
            }
        }

        int left = len - evenlen;// 剩余位数
        if (left > 0) {
            int i = ((arr[evenlen] & 0xff) << 10) | (left == 2 ? ((arr[len - 1] & 0xff) << 2) : 0);

            dest[destlen - 4] = encodeTable[i >> 12];
            dest[destlen - 3] = encodeTable[(i >>> 6) & 0x3f];

            if (isUrlSafe) {
                // 在URL Safe模式下,=为URL中的关键字符,不需要补充。空余的byte位要去掉。
                int urlSafeLen = destlen - 2;
                if (2 == left) {
                    dest[destlen - 2] = encodeTable[i & 0x3f];
                    urlSafeLen += 1;
                }
                byte[] urlSafeDest = new byte[urlSafeLen];
                System.arraycopy(dest, 0, urlSafeDest, 0, urlSafeLen);
                return urlSafeDest;
            } else {
                dest[destlen - 2] = (left == 2) ? encodeTable[i & 0x3f] : (byte) '=';
                dest[destlen - 1] = '=';
            }
        }
        return dest;
    }
}

 

public class StringUtils {

    public static boolean isEmpty(String str) {
        return null == str || str.isEmpty();
    }

    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 如果给定字符串{@code str}中不包含{@code appendStr},则在{@code str}后追加{@code appendStr};
     * 如果已包含{@code appendStr},则在{@code str}后追加{@code otherwise}
     *
     * @param str       给定的字符串
     * @param appendStr 需要追加的内容
     * @param otherwise 当{@code appendStr}不满足时追加到{@code str}后的内容
     * @return 追加后的字符串
     */
    public static String appendIfNotContain(String str, String appendStr, String otherwise) {
        if (isEmpty(str) || isEmpty(appendStr)) {
            return str;
        }
        if (str.contains(appendStr)) {
            return str.concat(otherwise);
        }
        return str.concat(appendStr);
    }

    /**
     * 编码字符串
     *
     * @param str 字符串
     * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
     * @return 编码后的字节码
     */
    public static byte[] bytes(CharSequence str, Charset charset) {
        if (str == null) {
            return null;
        }

        if (null == charset) {
            return str.toString().getBytes();
        }
        return str.toString().getBytes(charset);
    }

    /**
     * 解码字节码
     *
     * @param data 字符串
     * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
     * @return 解码后的字符串
     */
    public static String str(byte[] data, Charset charset) {
        if (data == null) {
            return null;
        }

        if (null == charset) {
            return new String(data);
        }
        return new String(data, charset);
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值