浙里办开发票据认证单点登陆、令牌获取用户信息

浙里办开发票据认证单点登陆、令牌获取用户信息,第1张

浙里办开发票据认证单点登陆、令牌获取用户信息(JAVA后端处理)

  最近在搞浙里办开发,周边的人里都没人接触过,以至于自己摸索搞起来比较心累。浙里办单点登陆需要在IRS上走申请,审核流程通过后,和指定的老师对接就可以了。

ak、sk获取

  组件申请审核通过后,组件申请提交人可以通过“公共应用组件系统-我申请的组件” https://csss.zj.gov.cn/verifyComList/applyNew 获取 AK/SK 信息。发送ak、sk、回调地址 还有系统名称给易和的老师,发送可以参考我的。

系统名称  XXXXXX系统
正式环境回调地址(测试环境发测试的地址)  https://mapi.zjzwfw.gov.cn/web/mgop/gov-open/zj/200XXXX676/reserved/index.html
SecretKey  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
AccessKey  8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8
阅读接入文档

  通过对文档的阅读,锁定到文档目录4.0.1的票据认证接口和4.2.3的根据令牌获取用户信息接口。

接口调用 controller
/**
 * 浙里办用户信息Controller
 *
 * @author xxxxxx
 * @date 2022/4/11
 */

import com.ruoyi.common.constant.PipelineConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.zjasm.zlb.service.IZlbClientService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Api("浙里办用户信息")
@RestController
@RequestMapping("/zlb/client")
public class ZlbClientController {

    @Autowired
    private IZlbClientService zlbClientService;

    private static final Logger logger = LoggerFactory.getLogger(ZlbClientController.class);

    /**
     * 获取用户临时授权码authCode
     */
    @ApiOperation(value = "获取用户登陆票据ticket", notes = "获取用户登陆票据ticket", httpMethod = "GET")
    @GetMapping("/getClientTicket/{ticket}")
    public AjaxResult getClientTicket(
            @ApiParam(name = "票据ticket", value = "获取用户登陆票据ticket", required = true) @PathVariable String ticket) {
        if (StringUtils.isEmpty(ticket) || "undefined".equals(ticket)) {
            return AjaxResult.error(PipelineConstants.MSG_ERROR_PARAMETER_WRONG);
        }
        logger.info("获取用户登陆票据ticket=" + ticket);
        return zlbClientService.getClientTicketCode(ticket);
    }

    /*
     * 根据令牌获取用户详细信息
     */
    @ApiOperation(value = "根据令牌token获取用户详细信息", notes = "根据令牌token获取用户详细信息", httpMethod = "GET")
    @GetMapping("/getClientInfo/{token}")
    public AjaxResult getClientInfoByToken(
            @ApiParam(name = "令牌token", value = "需要获取的用户令牌token", required = true) @PathVariable String token) {
        if (StringUtils.isEmpty(token) || "undefined".equals(token)) {
            return AjaxResult.error(PipelineConstants.MSG_ERROR_PARAMETER_WRONG);
        }
        logger.info("用户令牌token=" + token);
        return zlbClientService.getClientInfoByToken(token);
    }

}
IService接口
import com.ruoyi.common.core.domain.AjaxResult;

/**
 * 浙里办身份认证
 *
 * @author xxxxxx
 * @date 2022/4/14
 */
public interface IZlbClientService {

    public AjaxResult getClientTicketCode(String ticket);

    public AjaxResult getClientInfoByToken(String token);
}
service实现类

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.PipelineConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.zjasm.zlb.model.ZlbClientInfo;
import com.zjasm.zlb.model.ZlbTicketClientInfo;
import com.zjasm.zlb.service.IZlbClientService;
import com.zjasm.zlb.utils.HmacAuthUtil;
import com.zjasm.zlb.utils.HttpUtil;
import org.apache.http.client.methods.HttpPost;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 浙里办用户认证Service
 *
 * @author xxxxxx
 * @date 2022/4/14
 */
@Service
public class ZlbClientServiceImpl implements IZlbClientService {

    /**
     * token验证处理
     */
    @Resource
    private TokenService tokenService;
    /**
     * 用户角色表处理
     */
    @Resource
    private SysRoleMapper sysRoleMapper;

    /**
     * 初始密钥(仅正式ak和sk,没有测试ak和sk)
     */
    private static final String ACCESS_KEY = "8******************************8";
    private static final String APP_SECRET = "0******************************e";

    /**
     * 接口请求
     */
    private final HttpUtil httpUtil = HttpUtil.getInstance();
    /**
     * 日志打印
     */
    private static final Logger logger = LoggerFactory.getLogger(ZlbClientServiceImpl.class);

    /**
     * 票据认证
     *
     * @param ticket 票据
     * @return 用户认证信息
     */
    @Override
    public AjaxResult getClientTicketCode(String ticket) {
        String url = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220228000002/sso/servlet/simpleauth";
        // 接口请求方法
        String method = "POST";
        // 封装请求参数
        Map<String, String> header = HmacAuthUtil.generateHeader(url, method, ACCESS_KEY, APP_SECRET);
        // 创建POST请求
        HttpPost httpPost = new HttpPost(url);
        Iterator<String> its = header.keySet().iterator();
        while (its.hasNext()) {
            String next = its.next();
            httpPost.addHeader(next, header.get(next));
        }
        // 拼接请求参数
        Map<String, String> params = new HashMap<String, String>(20);
        String time = getSecondTimestamp();
        params.put("servicecode", ACCESS_KEY);
        params.put("method", "ticketValidation");
        // 时间戳,当前时间
        params.put("time", time);
        // MD5(servicecode+servicepwd+time)参数servicepwd为组件平台的SecretKey
        params.put("sign", Md5Utils.hash(ACCESS_KEY + APP_SECRET + time));
        // 票据
        params.put("st", ticket);
        // 返回数据类型
        params.put("datatype", "json");
        String result = httpUtil.sendHttpPost(httpPost, params);
        logger.info("浙里办用户认证接口请求结果:" + result);
        JSONObject resultJson = JSONObject.parseObject(result);
        // 请求结果
        String resultCode = resultJson.getString("result");
        /** 自定义处理结果 
        ticket失效:{"result":"6001","errmsg":"st已经超时失效"}
		请求成功:{"result":"0","errmsg":"成功","token":"8a118xxxx7435-commonToken","userid":"8a118a4xxxxxxx414b84473","loginname":"xxxxxx","orgcoding":"xxxxxx","username":"xxx"}
        */
        
        return null;
    }

    @Override
    public AjaxResult getClientInfoByToken(String token) {
        String url = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220228000004/sso/servlet/simpleauth";
        // 接口请求方法
        String method = "POST";
        // 封装请求参数
        Map<String, String> header = HmacAuthUtil.generateHeader(url, method, ACCESS_KEY, APP_SECRET);
        // 创建POST请求
        HttpPost httpPost = new HttpPost(url);
        Iterator<String> its = header.keySet().iterator();
        while (its.hasNext()) {
            String next = its.next();
            httpPost.addHeader(next, header.get(next));
        }
        // 拼接请求参数
        Map<String, String> params = new HashMap<String, String>(20);
        String time = getSecondTimestamp();
        params.put("servicecode", ACCESS_KEY);
        params.put("method", "getUserInfo");
        // 时间戳,当前时间
        params.put("time", time);
        // MD5(servicecode+servicepwd+time)参数servicepwd为组件平台的SecretKey
        params.put("sign", Md5Utils.hash(ACCESS_KEY + APP_SECRET + time));
        // 票据
        params.put("token", token);
        // 返回数据类型
        params.put("datatype", "json");
        String result = httpUtil.sendHttpPost(httpPost, params);
        logger.info("浙里办用户认证接口请求结果:" + result);
        JSONObject resultJson = JSONObject.parseObject(result);
        // 请求结果
        String resultCode = resultJson.getString("result");
        if (PipelineConstants.MSG_INFO_ZLB_STATUS_SUCCESS.equals(resultCode)) {
            // 根据token获取用户信息
            ZlbClientInfo zlbClientInfo = JSONObject.parseObject(result, ZlbClientInfo.class);
            logger.info("根据token获取用户信息ZlbClientInfo:" + zlbClientInfo.toString());
            return AjaxResult.success(zlbClientInfo);
        }
        return AjaxResult.error(resultCode);
    }

    /**
     * 获取时间戳,当前时间(年月日时分秒)
     *
     * @return 时间戳,当前时间(年月日时分秒)例如:2009年10月10日 12时12分12秒格式为20091010121212
     */
    private static String getSecondTimestamp() {
        // 时间戳,当前时间(年月日时分秒)
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        return formatter.format(new Date());
    }

utils工具类
  • HmacAuthUtil.java
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 浙里办加密工具类
 */
@Slf4j
public class HmacAuthUtil {

    /**
     * 构造请求 header
     *
     * @param urlStr        请求url,全路径格式,比如:https://bcdsg.zj.gov.cn/api/p/v1/user.get
     * @param requestMethod 请求方法,大写格式,如:GET, POST
     * @param accessKey     应用的 AK
     * @param secretKey     应用的 SK
     * @return
     */
    public static Map<String, String> generateHeader(String urlStr, String requestMethod, String accessKey, String secretKey) {
        log.info("params,urlStr={},requestMethod={},accessKey={},secretKey={}", urlStr, requestMethod, accessKey, secretKey);
        Map<String, String> header = new HashMap<>();
        try {
            DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
            dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
            String date = dateFormat.format(new Date());
            URL url = new URL(urlStr);
            URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);

            String canonicalQueryString = getCanonicalQueryString(uri.getQuery());

            String message = requestMethod.toUpperCase() + "\n" + uri.getPath() + "\n" + canonicalQueryString + "\n" + accessKey + "\n" + date + "\n";

            Mac hasher = Mac.getInstance("HmacSHA256");
            hasher.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));

            byte[] hash = hasher.doFinal(message.getBytes());

            // to lowercase hexits
            DatatypeConverter.printHexBinary(hash);

            // to base64
            String sign = DatatypeConverter.printBase64Binary(hash);
            header.put("X-BG-HMAC-SIGNATURE", sign);
            header.put("X-BG-HMAC-ALGORITHM", "hmac-sha256");
            header.put("X-BG-HMAC-ACCESS-KEY", accessKey);
            header.put("X-BG-DATE-TIME", date);
        } catch (Exception e) {
            log.error("generate error", e);
            throw new RuntimeException("generate header error");
        }
        log.info("header info,{}", header);
        return header;
    }

    private static String getCanonicalQueryString(String query) {
        if (query == null || query.trim().length() == 0) {
            return "";
        }
        List<Pair<String, String>> queryParamList = new ArrayList<>();
        String[] params = query.split("&");
        for (String param : params) {
            int eqIndex = param.indexOf("=");
            String key = param.substring(0, eqIndex);
            String value = param.substring(eqIndex + 1);
            Pair<String, String> pair = new Pair<String, String>(key, value);
            queryParamList.add(pair);
        }

        List<Pair<String, String>> sortedParamList = queryParamList.stream().sorted(Comparator.comparing(param -> param.getKey() + "=" + Optional.ofNullable(param.getValue()).orElse(""))).collect(Collectors.toList());
        List<Pair<String, String>> encodeParamList = new ArrayList<>();
        sortedParamList.stream().forEach(param -> {
            try {
                String key = URLEncoder.encode(param.getKey(), "utf-8");
                String value = URLEncoder.encode(Optional.ofNullable(param.getValue()).orElse(""), "utf-8")
                        .replaceAll("\%2B", "%20")
                        .replaceAll("\+", "%20")
                        .replaceAll("\%21", "!")
                        .replaceAll("\%27", "'")
                        .replaceAll("\%28", "(")
                        .replaceAll("\%29", ")")
                        .replaceAll("\%7E", "~")
                        .replaceAll("\%25", "%");
                encodeParamList.add(new Pair<>(key, value));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("encoding error");
            }
        });
        StringBuilder queryParamString = new StringBuilder(64);
        for (Pair<String, String> encodeParam : encodeParamList) {
            queryParamString.append(encodeParam.getKey()).append("=").append(Optional.ofNullable(encodeParam.getValue()).orElse(""));
            queryParamString.append("&");
        }

        return queryParamString.substring(0, queryParamString.length() - 1);
    }
}

  • HttpUtil.java
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpUtil {

    private final Logger logger = LoggerFactory.getLogger(getClass());


    private final RequestConfig requestConfig = RequestConfig.custom()
            .setSocketTimeout(8000)
            .setConnectTimeout(8000)
            .setConnectionRequestTimeout(8000)
            .build();

    private static HttpUtil instance = null;

    private HttpUtil() {
    }

    public static HttpUtil getInstance() {
        if (instance == null) {
            instance = new HttpUtil();
        }
        return instance;
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     */
    public String sendHttpPost(String httpUrl) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param params  参数(格式:key1=value1&key2=value2)
     */
    public String sendHttpPost(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param maps    参数
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpPost 地址
     * @param maps    参数
     */
    public String sendHttpPost(HttpPost httpPost, Map<String, String> maps) {
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return sendHttpPost(httpPost);
    }


    /**
     * 发送Post请求
     *
     * @param httpPost
     * @return
     */
    private String sendHttpPost(HttpPost httpPost) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPost);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return responseContent;
    }

    /**
     * 发送 get请求
     *
     * @param httpUrl
     */
    public String sendHttpGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpGet(httpGet);
    }

    /**
     * 发送 get请求Https
     *
     * @param httpUrl
     */
    public String sendHttpsGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpsGet(httpGet);
    }

    /**
     * 发送Get请求
     *
     * @param httpGet
     * @return
     */
    public String sendHttpGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return responseContent;
    }

    /**
     * 发送Get请求Https
     *
     * @return
     */
    private String sendHttpsGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
            DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
            httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return responseContent;
    }
}
pom文件

MAVEN引入的Jar包比较多,这里简单列举几个必须的。

        
        <dependency>
            <groupId>org.apache.httpcomponentsgroupId>
            <artifactId>httpclientartifactId>
            <version>4.5.13version>
        dependency>

        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.16.10version>
            <scope>providedscope>
        dependency>
前端参考

前端的代码就不再列举了,可以参考

https://blog.csdn.net/Xiang_Gong_Ya_/article/details/121991249

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/875779.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存