浙里办微信小程序上架

news2024/9/23 12:47:53

一、概述

本指南旨在为“浙里办”单点登录组件提供接入指南,“浙里办”单点登陆组件,上架在IRS,为上架在IRS的应用,提供统一的单点登录解决方案,现阶段仅支持微信端的接入。

二、服务创建

IRS 应用管理员在 IRS 应用发布服务侧进行“应用发布注册”。
注意事项
1、IRS 应用系统查询没有应用信息,可通过 IRS 应用编目查询该应用的 IRS 应用管理员
信息。
2、IRS 应用管理员添加的开发商信息需要有浙政钉账号,由服务侧应用建设单位提供,
用于 IRS 应用发布开发商工作台进行服务部署。

3、应用接入“浙里办”单点登录组件前,需要先获取AK&SK。

 

三、接入说明

接入前需要服务侧应用建设单位已完成在 IRS 应用编目工作。从开发部署到服务上架,需
要经历以下主要阶段:

 

四、接入规范

  1. 接入浙里办微信小程序的 H5 应用(以下简称应用), 应当符合同源发布及无障碍适老化等要求。
  2. 应用应当在浙江省一体化数字资源系统(以下简称 IRS)发布,并使用统一的域名 https://mapi.zjzwfw.gov.cn/,作为接入微信小程序的前置条件。应用上架 IRS,应遵循 IRS 相关规范。
  3. 应用接入浙里办微信小程序,应当按照本指南操作步骤与注意事项,进行微信端的兼容适配。

五、操作步骤

“浙里办”微信小程序接入工作流程图:

1、单点登录适配 

Java代码案例:

(1)Constants  定义所有常量

/**
 * @author jie.chen
 * @date 2022-03-30 15:24
 */
public interface Constants {

    /**
     * 单点登录 ticketId换token的地址
     */
//    String ACCESS_TOKEN_URL = "https://bcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220329000007/uc/sso/access_token";政务外网
     //互联网
    String ACCESS_TOKEN_URL = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220329000007/uc/sso/access_token";
    /**
     * 单点登录 token获取用户信息地址
     */
//    String GET_USER_INFO_URL = "https://bcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220329000008/uc/sso/getUserInfo";政务外网
    //互联网
    String GET_USER_INFO_URL = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220329000008/uc/sso/getUserInfo";

    /**
     * IRS请求携带的请求头
     */
    String X_BG_HMAC_ACCESS_KEY = "X-BG-HMAC-ACCESS-KEY";
    String X_BG_HMAC_SIGNATURE = "X-BG-HMAC-SIGNATURE";
    String X_BG_HMAC_ALGORITHM = "X-BG-HMAC-ALGORITHM";
    String X_BG_DATE_TIME = "X-BG-DATE-TIME";

    /**
     * IRS签名算法
     */
    String DEFAULT_HMAC_SIGNATURE = "hmac-sha256";

    /**
     * 应用ID
     */
    String APP_ID = "20******33";
    /**
     * 微信端固定值为weixin
     */
    String WEIXIN_ENDPOINT_TYPE = "weixin";


    /**
     * IRS 申请组件生成的AK
     */
    String IRS_AK = "********************************";
    /**
     * IRS 申请组件生成的SK
     */
    String IRS_SK = "********************************";


    String TOKEN_SESSION_KEY = "sessionAccessToken";
    String USER_INFO_KEY = "sessionUserInfo";

}

(2)IrsUtils

/**
 * @author jie.chen
 * @date 2022-03-30 15:28
 */
public class IrsUtils {


    @SneakyThrows
    public static IrsSignRes sign(String url, String method) {
        UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(url).build();
        uriComponents = uriComponents.encode();
        List<String> queryArr = new ArrayList<>();
        MultiValueMap<String, String> queryParams = uriComponents.getQueryParams();
        for (Map.Entry<String, List<String>> next : queryParams.entrySet()) {
            for (String va : next.getValue()) {
                if (va == null) {
                    queryArr.add(next.getKey() + "=");
                } else {
                    queryArr.add(next.getKey() + "=" + va);
                }
            }
        }
        //按照字典排序
        Collections.sort(queryArr);
        ///Tue, 09 Nov 2021 08:49:20 GMT
        DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        String dateTime = dateFormat.format(new Date());

        String signStr = method.toUpperCase() + "\n" +
                //拼接url path
                uriComponents.getPath() + "\n" +
                //拼接url query
                String.join("&", queryArr) + "\n" +
                Constants.IRS_AK + "\n" +
                dateTime + "\n";

        String sign = hmacSha256Base64(signStr, Constants.IRS_SK);

        IrsSignRes res = new IrsSignRes();

        res.setSignature(sign);
        res.setAccessKey(Constants.IRS_AK);
        res.setDateTime(dateTime);
        res.setAlgorithm(Constants.DEFAULT_HMAC_SIGNATURE);
        return res;
    }


    @SneakyThrows
    private static String hmacSha256Base64(String content, String key) {
        Mac hmacSHA256 = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        hmacSHA256.init(secretKey);
        byte[] bytes = hmacSHA256.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(bytes);
    }

    public static void main(String[] args) {

        System.out.println(sign("https://bcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220329000007/uc/sso/getUserInfo", "POST"));
    }

}

(3)IrsSignRes

/**
 * @author jie.chen
 * @date 2022-03-30 15:28
 */
@Data
public class IrsSignRes {
    private String accessKey;
    private String signature;
    private String algorithm;
    private String dateTime;
}

(4)AuthService 业务实现类

/**
 * @author jie.chen
 * @date 2022-03-30 15:49
 */
@Component
public class AuthService {


    @Autowired
    private RestTemplateBuilder restTemplateBuilder;

    private RestTemplate restTemplate;

    @PostConstruct
    void init() {
        restTemplate = restTemplateBuilder.build();
    }


    public String getTokenByTicketId(String ticketId) {

        HttpHeaders headers = getHttpHeaders(Constants.ACCESS_TOKEN_URL);
        JSONObject body = new JSONObject();
        body.put("appId", Constants.APP_ID);
        body.put("ticketId", ticketId);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);

        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(Constants.ACCESS_TOKEN_URL, request, String.class);
        return checkResponse(stringResponseEntity).getJSONObject("data").getString("accessToken");
    }


    public JSONObject getUserInfoByToken(String accessToken) {
        HttpHeaders headers = getHttpHeaders(Constants.GET_USER_INFO_URL);
        JSONObject body = new JSONObject();
        body.put("token", accessToken);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);

        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(Constants.GET_USER_INFO_URL, request, String.class);
        return checkResponse(stringResponseEntity).getJSONObject("data");
    }

    private JSONObject checkResponse(ResponseEntity<String> stringResponseEntity) {
        if (!stringResponseEntity.getStatusCode().is2xxSuccessful()) {
            //请求失败
            throw new RuntimeException("status:" + stringResponseEntity.getStatusCodeValue() + " " + stringResponseEntity.getBody());
        }
        JSONObject result = JSON.parseObject(stringResponseEntity.getBody());
        if (result.containsKey("errorCode") && result.getString("errorCode") != null && !result.getBooleanValue("success")) {
            //业务错误
            throw new RuntimeException(result.toString());
        }
        return result;
    }

    private HttpHeaders getHttpHeaders(String url) {
        IrsSignRes res = IrsUtils.sign(url, "POST");

        HttpHeaders headers = new HttpHeaders();
        headers.add(Constants.X_BG_HMAC_ACCESS_KEY, res.getAccessKey());
        headers.add(Constants.X_BG_HMAC_ALGORITHM, res.getAlgorithm());
        headers.add(Constants.X_BG_HMAC_SIGNATURE, res.getSignature());
        headers.add(Constants.X_BG_DATE_TIME, res.getDateTime());
        return headers;
    }

(5)LoginController 接口测试

/**
 * @author hejun
 * @since 2022-02-22 10:46:11
 */
@RestController
@RequestMapping("/user")
@Api(tags="用户登录")
@Slf4j
public class LoginController extends ProBaseController {
    @GetMapping(value = "zlbWxLoginTest")
    @ApiOperation(value = "测试浙里办微信小程序登录接口", notes = "测试浙里办微信小程序登录接口后端接口")
    public String zlbWxLoginTest(@RequestParam @ApiParam(name = "st", value = "浙里办 ticketId", required = true)String st) {
        try {

            return buildResultStr(buildSuccessResultData(userService.getUserBeanByTicketId(st)));
        }catch (Exception e) {
            logError(log, e);
            return buildResultStr(buildErrorResultData(e.getMessage()));
        }
    }
}

(6) UserServiceImpl 浙里办用户体系转换

/**
 * 用户表(User)表服务实现类
 *
 * @author hejun
 * @since 2022-02-22 10:02:16
 */
@Service("userService")
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private AuthService authService;

    @Override
    public UserBean getUserBeanByTicketId(String ticketId){
        UserBean userBean = new UserBean();
        //1. 通过ticketId 换取 accessToken
        String token = authService.getTokenByTicketId(ticketId);
        //3. 通过accessToken 获取用户信息
        JSONObject userInfo = authService.getUserInfoByToken(token);
        JSONObject personInfo = userInfo.getJSONObject("personInfo");
        String phone = personInfo.get("phone").toString();
        userBean.setMobile(phone);
        userBean.setUsername(personInfo.get("userName").toString());
        userBean.setIdnum(personInfo.get("idNo").toString());
        userBean.setUserid(personInfo.get("userId").toString());
        String login = null;
        if (StringUtils.isNotNullString(phone)){
            login = this.login(phone);
            userBean.setToken(login);
            log.info("token------------------------------", login);
        }
        return userBean;
    }
    /**
     * 通过手机号登录
     *
     * @return token
     */
    @Override
    public String login(String phone) {
        User user = this.getUserByPhone(phone);
        if (user == null){
            user = new User();
            user.setMobile(phone);
            this.insert(user);
        }
        //生成token
        String token = getUserRsid(phone);
        token = token.replaceAll("/","_");
        //token放入缓存
        JedisUtils.setObject(token,user,portalRsidCacheSeconds);
        //返回token
        return token;
    }


}

六、接口调用方式

请以POST方式提交请求参数以application/json形式提交

    1. 鉴权参数说明

“浙里办”单点登录,HTTP请求都必须在请求头(HTTP Header)中设置如下4个参数:

参数名

是否必填

类型

说明

X-BG-HMAC-SIGNATURE

string

API输入参数签名结果

X-BG-HMAC-ALGORITHM

string

签名的摘要算法,当前仅支持hmac-sha256。

X-BG-HMAC-ACCESS-KEY

string

分配给应用的accessKey,例如:12345678。

X-BG-DATE-TIME

string

时间戳,时区为GMT+8,格式为:Tue, 09 Nov 2021 08:49:20 GMT。服务端允许客户端请求最大时间误差为100秒。

其中X-BG-HMAC-SIGNATURE的计算公式为:

signature = HMAC-SHA256-HEX(secret_key,signing_string)

各字段解释如下:

  1. secret_key为接口申请完成后获取到的secret_key
  2. signing_string由请求方法、URI、请求参数等拼接获得,具体如下:

HTTP_METHOD+\n+HTTP_URI+\n+QUERY_STREAM+\n+X-BG-HMAC-ACCESS-KEY+\n+X-BG-DATE+\n

参数解释如下图,详细代码可参考签名计算代码

参数名

说明

HTTP METHOD

指 HTTP 协议中定义的 GET、PUT、POST 等请求方法,必须使用全大写的形式。

HTTP URI

请求路径,要求必须以“/”开头,不以“/”开头的需要补充上,空路径为“/”

X-BG-DATE

请求头中的 Date ( GMT 格式 )格式为:“Tue, 09 Nov 2021 08:49:20 GMT”

QUERY_STREAM

是对于 URL 中的 query( query 即 URL 中?后面的 key1=valve1&key2=valve2 字符串)进行编码后的结果。以 key 按照字典顺序( ASCII 码由小到大)排序,并使用 & 符号连接起来,生成相应的query_string。

  • 接口说明
    1. 基于单点登录票据换取请求token
    1. 请求地址

 /uc/sso/access_token

    1. 入参

参数

类型

描述

ticketId

String

单点登录票据

appId

String

AppId

    1. 出参

参数

类型

描述

errorCode

String

错误码

errorMsg

String

错误信息

success

Boolean

请求是否成功

data

Object

响应体

|- accessToken

String

获取用户信息token

    1. 错误码

错误码

描述

C-USER-SSO-TICKET-INVALID

ticket非法

    1. 基于token获取用户信息
  1. 请求地址

/uc/sso/getUserInfo

  1. 入参

参数

类型

描述

token

String

获取用户信息token

  1. 出参

参数

类型

描述

success

Boolean

请求是否成功

errorCode

String

错误码

errorMsg

String

错误信息

data

Object

响应体

|- userType

String

用户类型,PERSON

个人/LEGAL_PERSON

法人

|- personInfo

Object

个人用户信息,当前登陆自然人的信息

|-- userId

String

主键

|-- userName

String

个人姓名

|-- idType

String

ID_CARD:身份证,PASSPORT:护照,OFFICER_CARD:军官证,MAINLAND_TRAVEL_PERMIT_FOR_HONGKONG_AND_MACAO_RESIDENTS:港澳居民来往内地通行证,MAINLAND_TRAVEL_PERMIT_FOR_TAIWAN_RESIDENTS:台湾居民来往大陆通行证,FOREIGN_PERMANENT_RESIDENT_ID_CARD:外国人永久居留身份证,FOREIGN_PASSPORT:外籍人士护照,DIPLOMACY_PASSPORT:外交护照,OFFICIAL_PASSPORT:公务护照,SOLDIER_CARD:士兵证,OFFICER_RETIRE_CARD:军官离退休证,GANG_AO_TAI_RESIDENCE_CART:港澳台居民居住证,GANG_AO_ID_CART:港澳居民身份证,UNIFIED_SOCIAL_ID:统一社会信用代码,OTHER:其他

|-- outerIdType

String

外部证件类型

|-- idNo

String

证件编号

|-- attnUserType

String

法人经办人时用户类型,评级

|-- phone

String

手机号

|-- email

String

邮箱

|-- nation

String

民族

|-- gender

String

性别

|-- birthday

String

生日

|-- certKey

String

身份散列值

|-- attributes

Object

额外属性

|- legalPersonInfo

Object

法人用户信息,比如公司相关的信息

|-- name

String

法人名称

|-- unifiedSocialId

String

社会统一信用代码

|-- orgType

String

法人类型

|-- attnName

String

经办人姓名

|-- attnPhone

String

经办人手机号

|-- attnIdType

String

经办人证件类型

|-- attnIdNo

String

经办人证件号码

|-- attnUserType

String

经办人用户等级

|-- principal

String

法人代表人姓名

|-- gender

Integer

法人代表人性别

|-- nation

Integer

法人代表人民族

|-- idType

Integer

法人代表人证件类型

|-- outerIdType

String

法人代表人外部证件类型

|-- idNo

String

法人代表人证件号码

|-- principalUserId

String

法人代表唯一键

|-- corpId

String

法人唯一键

|-- attributes

Object

额外属性

|- organizationInfoList

Array

所属组织信息

|-- orgId

String

组织主键

|-- oid

String

Alias for orgId

|-- parentId

String

父组织主键

|-- pid

String

Alias for parentId

|-- name

String

组织机构简称

|--fullName

String

组织机构全称

|--devCoding

String

组织后缀

|--leafFlag

Boolean

是否叶子标志

|--orderBy

Integer

排序号,从小到大

  1. 错误码

错误码

描述

C-USER-SSO-TOKEN-INVALID

token非法

C-USER-SSO-USER-EMPTY

用户信息为空

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32302.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kali系统MSF模块暴力破解MySQL弱口令漏洞

一、实验环境 1.攻击方&#xff1a; 攻击环境使用KALI系统&#xff08;使用虚拟机搭建&#xff09;的Metasploit模块&#xff0c;msfconsole是metasploit中的一个工具&#xff0c;它集成了很多漏洞的利用的脚本&#xff0c;并且使用起来很简单的网络安全工具。 这里要特别强…

代码随想录64——额外题目【哈希表、字符串】:205同构字符串、1002查找常用字符、925长键按入、844比较含退格的字符串

文章目录1.205同构字符串1.1.题目1.2.解答2.1002查找常用字符2.1.题目2.2.解答3.925长键按入3.1.题目3.2.解答4.844比较含退格的字符串4.1.题目4.2.解答4.2.1.使用栈4.2.2.从后往前双指针1.205同构字符串 参考&#xff1a;代码随想录&#xff0c;205同构字符串&#xff1b;力扣…

MySQL数据库的索引

文章目录一、索引是什么&#xff1f;索引的作用二、索引的使用查看索引创建索引删除索引三、索引的底层一、索引是什么&#xff1f; 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#…

[附源码]java毕业设计医疗预约系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SQL注入原理、过程、防御方案、RASP概念

一、sql注入原理 SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的语句上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息…

第1关:Hive的安装与配置

为了完成本关任务&#xff0c;你需要掌握&#xff1a; 1.Hive的基本安装&#xff1b; 2.Mysql的安装与设置&#xff1b; 3.Hive 的配置。 注意&#xff1a;本关实训Hive的安装与配置建立在Hadoop已安装配置好的情况下。 Hive 的基本安装 从 官网 下载Hive二进制包&#xf…

优维科技CTO黎明访谈实录:“大场景+小算法”构建AiOps运维技术哲学

智能运维、自动化运维发展到现在&#xff0c;已经有将近7成的IT管理者学会利用大数据、人工智能产品及解决方案赋能团队&#xff0c;在生产效率、适应性和决策能力等层面实现了切实有效的正向转型。 今天的中国企业&#xff0c;已经在云端新基建、数字化转型的浪潮中实现降本增…

美食杰项目 -- 菜品信息(五)

目录前言&#xff1a;具体实现思路&#xff1a;步骤&#xff1a;1. 展示美食杰菜谱大全效果2. 引入element-ui3. 代码总结&#xff1a;前言&#xff1a; 本文给大家讲解&#xff0c;美食杰项目中 实现菜品信息页的效果&#xff0c;和具体代码。 具体实现思路&#xff1a; 跳转…

[附源码]java毕业设计疫情防控期间人员档案追寻系统设计与实现论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

bash shell 初体验-尚文网络xUP楠哥

~~全文共1139字&#xff0c;阅读需约5分钟。 进Q群11372462&#xff0c;领取专属报名福利&#xff0c;包含云计算学习路线图代表性实战训练大厂云计算面试题资料! # bash shell 简介 我们在操作Linux系统时&#xff0c;绝大部分情况是通过命令行的方式输入指令&#xff0c;Li…

小型企业建立人力资源团队的 5 个步骤

作为小企业主&#xff0c;设置人力资源运营可能不是您的首要任务。但是&#xff0c;随着您扩大运营规模和员工人数&#xff0c;您可能会遇到合规性和员工敬业度问题&#xff0c;从而阻碍您的业务增长。组建一个团队来照顾您的人力资源运营和员工可以让您专注于改进您的产品和满…

【JVM】字节码技术:手撕 多态执行原理

一、源文件 package org.example.classLoading;import java.io.IOException; /*** 演示多态原理&#xff0c;注意加上下面的 JVM 参数&#xff0c;禁用指针压缩* -XX:-UseCompressedOops -XX:-UseCompressedClassPointers*/ public class PolymorphicTest {public static void…

【序列召回推荐】(task2)序列召回GRU4Rec和faiss使用

学习总结&#xff1a; 一般的RNN模型我们的输入和输出是什么&#xff0c;我们对RNN输入一个序列 X[x1,x2,...,xn]X [x^1,x^2,...,x^n]X[x1,x2,...,xn] &#xff0c;注意我们序列中的每一个节点都是一个向量&#xff0c;那么我们的RNN会给我们的输出也是一个序列 Y[y1,y2,...,…

[附源码]SSM计算机毕业设计江苏策腾智能科技公司人事管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

.net----特性

特性特性的概念和使用特性&#xff08;Attribute&#xff09;特性形式特性类参数预定义通用特性类ConditionalAttribute类ObsoleteAttribute类AttributeUsageAttribute类全局特性自定义特性类使用反射访问特性特性的概念和使用 特性&#xff08;Attribute&#xff09; 特性类&…

http请求报头header

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一.认识请求报头&#xff08;header&#xff09; 1.Host 2.content-length 3.content-type 常见的三种格式 小结 二.User-Agent(简称UA) 三.Referer 四.C…

进程创建进程终止进程等待

目录前言一、进程创建1.fork()函数&#xff08;1&#xff09;fork()函数的基本认识进程调用fork()函数之后&#xff0c;控制权转移到内核中的fork()代码之后&#xff0c;内核做了啥&#xff1f;&#xff08;2&#xff09;实验&#xff1a;使用fork()函数创建进程&#xff08;3&…

跨境电商卖家必知的【圣诞节营销】终极指南(一)

关键词&#xff1a;圣诞节营销、跨境电商卖家 不知不觉又到了年底&#xff0c;而对于跨境电商来说也是非常重要的一段促销时期&#xff0c;也许您已经制定了相关的圣诞节营销大促&#xff0c;但今天我们还是想告诉您一些2022年非常棒的销的创意想法&#xff0c;希望能帮助您提升…

Spring Cloud Alibaba(四)

openFeign配置日志 一、openFeign的日志级别&#xff1a; NONE&#xff1a;不记录日志 (默认). BASIC&#xff1a;只记录请求方法、url、响应状态码和执行时间。 HEADERS&#xff1a;在basic的基础上&#xff0c;增加请求和响应头 FULL&#xff1a;记录请求和响应的头、body…

PyTorch搭建RNN联合嵌入模型(LSTM GRU)实现视觉问答(VQA)实战(超详细 附数据集和源码)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 一、视觉问题简介 视觉问答&#xff08;VQA&#xff09;是一种同时设计计算机视觉和自然语言处理的学习任务。简单来说&#xff0c;VQA就是对给定的图片进行问答&#xff0c;一个VQA系统以一张图片和一个关于这张图片形式自…