版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章身份认证
5.1概述5.2口令认证5.3零知识证明思考题
实验5身份认证系统的设计与实现
5.1概述5.1.1认证的基本概念认证是指对各种证据材料进行审查和分析,确定其真实性和证明力,从而做出判定结论的活动。信息安全领域的认证主要是指确定实体的身份、来源和完整性,分为身份认证和消息认证两大类。身份认证就是证实对象身份的过程,即验证者确信一个实体正是符合某种条件的实体,没有被假冒。消息认证是鉴定某个指定的数据是否来源于某个特定的实体,没有被篡改。身份认证只证实实体的身份;消息认证除了消息的合法和完整外,还需要明确消息的含义。身份认证和消息认证的区别还体现在,身份认证一般都是实时的,消息认证一般不提供时间性。在消息认证中,声称者未必涉及在当前的通信活动中,数据项可能已经通过许多系统被重放,这些系统可能或没有被认证。数据项可能在途中被存储相当的周期,但也未必能免遭复制、重排序或丢失。认证可以对抗假冒攻击,是最重要的安全服务之一,所有其他的安全服务一般都依赖于该服务,例如,访问控制服务的执行需要依赖于确知的身份。
5.1.2身份认证系统的组成和设计要求一个身份认证系统最少由示证者、示证信息、验证者、验证信息和验证协议五部分组成,在发生纠纷时,还需要可信赖第三方的参与。一个完善的身份认证系统应该满足如下要求:
(1)验证者正确识别合法示证者的概率极大化。
(2)不具有可传递性。
(3)攻击者欺骗验证者成功的概率要小到可以忽略的程度。
(4)计算有效性。
(5)通信有效性。
(6)秘密参数能安全存储。在理论上,相互认证可通过组合两个单向认证来实现。然而,这种组合需要被仔细地考察,因为有可能这样的组合易受窃听重放攻击。另外,编写设计协议消息数比相应的单向交换协议消息数的两倍少得多的相互认证交换协议是可能的。5.1.3身份认证的方法身份认证一般通过下述一种或多种方法实现:
(1)示证者所知道的秘密(Whatyouknow,所知)。如口令、密码、身份证号码、个人识别码(PIN)、出生日期等,如图5-1所示。
(2)示证者所拥有的信物(Whatyouhave,所有),如证章、信用卡、ID卡、证书、密钥盘等,如图5-2所示。图5-1“所知”型身份认证图5-2“所有”型身份认证
(3)示证者所具有的生物特征(Whatyouare,所是)。在计算机发明以前,人们依靠相貌和声音进行认证,照相技术出现后,照片认证方法得以广泛使用。指纹技术和DNA指纹技术是犯罪领域身份认证的主要手段;虹膜和视网膜、字迹,甚至敲击键盘的方式都可以用作生物特征测定。生物特征测定方法的优点是不需要像口令和密码那样有记忆负担,而且相同的特征可以在任何地方使用,缺点是生物特征认证系统价格较为昂贵。图5-3给出了一些“所是”型身份认证的例子。图5-3“所是”型身份认证
(4)示证者所在的位置(Whereyouare,所在)。例如,实体的IP地址,实体所在的大地测量位置(GPS)、特定的大门、特殊的终端、特别的访问设备等。基于位置的认证技术最适合保护固定的场所,但不太适合认证移动用户。为了强化安全,在资金、接受程度和计算代价允许的情况下,可以把上述认证方法组合起来使用,实现所谓的“多重认证”或“强力认证”。
5.1.4挑战-应答协议(challenge-responseprotocol)挑战-应答协议在身份认证中具有十分重要的地位,其作用主要用来抗击重放攻击,实现身份认证的实时性。一个广义的挑战-应答协议可以简单描述如下:
(1) A→B:C1;
(2) B→A:R1,C2;
(3) A→B:R2。其中,C1是A发送给B的挑战字串,通常为一个不可预计的随机数,当B收到该消息后,回复给A一个应答数R1和另外一个自己生成的挑战字串C2,紧接着A给B一个应答R2。
上述协议的目的在于:如果应答R1和R2都是如发送挑战方所预期的那样的话,应该能够完成一个相互的认证过程。为了防止机器对挑战信息的自动应答,在2000年由卡内基梅隆大学发明了称为全自动计算机和人区分图灵测试的验证码,这种测试能使人轻易通过而计算机无法通过。验证码一般分为文本验证码、图片验证码和问题验证码。在实用中,文本验证码已被淘汰;图片验证码是根据一定的随机数生成算法来产生一个随机数字或符号,然后加入一些干扰像素,最终生成相应的用于验证的图片;问题验证码一般是在注册时选好多个问题信息,然后在应答时进行随机回答。5.1.5完整性校验和认证中秘密信息的存放是有要求的,例如,在基于口令的认证系统中,验证端不允许存储口令,只允许存储口令的完整性校验和。完整性校验和是由要加以保护的数据按照特定的方法计算出来的数值。数据的完整性靠反复计算校验和来证明正确有效。如果计算出来的数值与存储的数值相符,则说明数据没受到损害;反之,则认为数据已经受到损害。为行之有效,校验和必定是数据中每一位的函数。产生校验和的函数称为散列函数,一般靠Hash函数(如MD-5,SHA-256)来实现,这种函数具有单向(无法求逆)、输出定长等特点。关于Hash函数的进一步介绍参见第6章。5.2口令认证5.2.1两个口令认证协议例5-1一个不安全的口令认证系统如图5-4所示。在该系统中,用户把自己的身份ID连同口令一起传送给服务器,服务器端在口令文件或口令数据库中查出相应的用户ID和口令的Hash值,然后计算传过来的口令的Hash值,如果两个Hash值相等,则确认用户合法。图5-4一个不安全的口令认证系统上述系统中,服务器端对用户口令信息的存储采用了完整性校验和的存储形式,没有直接存储口令本身,这是值得称道的。但是,上述系统无法抗击窃听攻击,更不能抗击重放攻击。遗憾的是,很多同学在设计基于口令的认证系统时采用了这一方案。通过对上述设计方案的分析,我们更进一步明确了,一个好的认证协议必须要具有保密性和时效性。需要保密的信息无论是在传输中还是在存储中都必须要加以保护,严防泄露。时效性也非常重要,它涉及到能否有效防止消息重放攻击。常见的消息重放攻击有4种形式,分别是:①攻击者简单复制一条消息,以后再重新发送;②攻击者可以在一个合法有效的时间窗内重放一个带时间戳的消息;③原始信息已经被拦截,无法到达目的地,而只有重放的信息到达目的地;④反向重放,消息发送者不能简单地识别发送的消息和收到的消息在内容上的区别。挑战-应答的方法可以抗击重放攻击,但这种方法不适应非连接性的应用,因为它要求在传输开始之前先有握手的额外开销,这就抵消了无连接通信的主要特点。例5-2一个基于挑战-应答协议的口令认证方案如图5-5所示。
图5-5一个基于挑战-应答协议的口令认证方案在该认证协议中,口令即是key。假如用户向服务器发出认证请求,服务器首先产生一个随机数(挑战)RS送给用户。用户把自己的身份IDU和自己产生的随机数RU连同RS一起作为自变量计算由Key控制的Hash值MAC,然后把IDU、RU和MAC发给服务器(应答)。服务器根据收到的IDU、RU和自己保留的RS重新计算MAC,然后与收到的MAC进行比较验证。从安全的角度衡量,上述协议显然优于例5-1中的认证协议。但上述认证协议中,没有说明口令在服务器端的存放方法。如果解决不了口令的存放问题,该协议显然不能用于大规模认证。那么上述协议是否就安全了呢?协议的安全性衡量是非常复杂的,这一方面需要对安全性进行精确的定义,另一方面还要对具体协议进行理论上的证明。很多使用多年、貌似安全的协议后来被证明是不安全的。目前,安全协议的形式化证明方面主要有以下3类研究方法,分别是:①基于推理结构型方法(如BAN逻辑);②基于攻击结构性方法(如模型检测);③基于证明结构性方法(如串空间模型)。5.2.2NTLM协议典型的基于口令的身份认证协议有PAP、CHAP、NTLM和Kerberos,因篇幅所限制,现就NTLM协议和Kerberos协议作一简单介绍。
NTLM是NTLANManager的缩写,NTLM协议是WindowsNT的标准安全协议,也是Windows2000内置三种基本安全协议之一。域(Domain)是WindowsNT网络中独立运行的单位。在一个域中,域控制器负责管理所有的用户账户,用户在域中其他服务器上没有账户,所有用户和服务器都信赖域控制器,WindowsNT中的域如图5-6所示。图5-6WindowsNT中的域用户的身份认证是通过域控制器实现的,具体的NTLM协议可如图5-7所示。上述协议中,用户密码是由用户注册的口令通过Hash函数得到的,只有用户和域控制器才知道密码。协议没有口令传输,使用了挑战-应答结构,因而能够抗击重放攻击。如果使用强口令,则上述协议比较安全。协议的一大缺点是用户访问每台服务器都需要域控制器的认证,容易导致瓶颈。图5-7NTLM协议示意图5.2.3Kerberos协议
Kerberos是由美国麻省理工学院人员开发的一种基于可信赖第三方的认证服务系统,能够使网络用户互相证明自己的身份。目前广泛使用的版本是Kerberos5.0。在Kerberos系统中,每一个参与者(Alice,Bob,etc.)被称为一个主体,它与密钥分配服务器(KDC)共享一把密钥(主密钥),客户对服务器的访问一般通过三个步骤实现,分别是:①客户向KDC进行身份认证,获取访问票据许可服务器的访问票据;②客户访问票据许可服务器获取访问应用服务器的票据;③客户向应用服务器出示访问票据,应用服务器根据票据决定是否提供服务。Kerberos协议的总体框架如图5-8所示。
图5-8Kerberos的认证总体框架
Kerberos的认证过程详细流程可分为如下三步:
(1)客户向KDC进行身份认证,获取访问票据许可服务器的访问票据,如图5-9所示。
(2)客户访问票据许可服务器获取访问应用服务器的票据,如图5-10所示。
(3)客户向应用服务器出示访问票据,服务器根据票据决定是否提供服务,如图5-11所示。图5-9客户向KDC进行认证图5-10客户获得访问应用服务器的票据图5-11客户提供票据来访问应用服务器5.3零 知 识 证 明在传统的使用口令或密码来证明自己身份的系统中,检验口令或密码的一方(人或系统)可以直接使用完整性校验和来冒充用户,原因是认证协议一般是公开的。零知识证明是由Goldwasser等人在20世纪80年代初提出的。它是指示证明者能够在不向验证者提供任何有用信息的情况下,使验证者相信某个论断是正确的。大量事实证明,零知识证明在密码学和信息安全中非常有用。
零知识证明实质上是一种涉及两方或更多方的协议,即两方或更多方完成一项任务所需采取的一系列步骤。证明者向验证者证明并使其相信自己知道或拥有某一消息,但证明过程中不能向验证者泄漏任何关于被证明消息的信息。在Goldwasser等人提出的零知识证明中,证明者和验证者之间必须进行交互,这样的零知识证明被称为交互式零知识证明。例5-3图5-12表示一个简单的迷宫,C与D之间有一道门,需要知道秘密口令才能将其打开。P向V证明自己能打开这道门,但又不愿向V泄露秘密口令。可采用如下协议:
(1) V在协议开始时停留在位置A。
(2) P一直走到迷宫深处,随机选择位置C或位置D。
(3) P消失后,V走到位置B,然后命令P从某个出口返回位置B。
(4) P服从V的命令,必要时利用秘密口令打开C与D之间的门。
(5) P和V重复以上过程n次。
图5-12例1中的一个简单迷宫例5-4一个简化的Fiat-Shamir身份识别方案。设n=pq,其中p和q是两个不同的大素数,x是模n的平方剩余,y是x的平方根。又设n和x是公开的,而p、q和y是保密的。证明者P以y作为自己的秘密。求解方程y2≡amodn与分解n是等价的,因此他人不知n的两个素因子p、q而计算y是困难的。P和验证者V通过交互证明协议,P向V证明自己掌握秘密y,从而证明了自己的身份。具体协议如:
(1) P随机选r(0<r<n),计算a≡r2modn,将a发送给V。
(2) V随机选e∈{0,1},将e发送给P。
(3) P计算b≡ryemodn,即e=0时,b=r;e=1时,b=rymodn。将b发送给V。
(4)若b2≡axemodn,V接受P的证明。如果P和V遵守协议,且P知道y,则应答b≡ryemodn应是模n下axe的平方根,在协议的第(4)步V接受P的证明。假冒的证明者只有能正确猜测V的询问才可以使V相信自己的身份。E能成功欺骗的最大概率是1/2,否则假设E以大于1/2的概率使V相信自己的证明,那么E知道一个a,对这个a他可正确地应答V的两个询问,即e=0和e=1,意味着E能计算b21≡amodn和b22≡axmodn,因而E能求出x的平方根y。将上述协议重复执行,则欺骗者欺骗成功的概率将逐步减小。
20世纪80年代末,Blum等人进一步提出了非交互零知识证明的概念,用一个短随机串代替交互过程并实现了零知识证明。非交互零知识证明的一个重要应用场合是需要执行大量密码协议的大型网络。思考题
(1)一般可以用哪些证据证明自己的身份,哪些生物特征可用于身份认证?
(2)挑战-应答协议在认证系统中的作用是什么?
(3)口令认证系统在设计中应该注意哪些问题?
(4)描述NTLM协议的认证过程。
(5)描述Kerberos协议的认证过程。
(6)什么是零知识证明?什么是非交互零知识证明?实验5身份认证系统的设计与实现
一、实验目的
(1)了解身份认证的重要意义和常用方法。
(2)深入理解消息摘要、随机数和挑战-应答等有关知识在认证协议中的作用。
(3)结合第五章内容,设计一个身份认证方案,给出相关实现代码。二、实验准备
(1)一旦黑客获取了目标机上的用户口令,就可以进入目标计算机,对目标机造成严重的安全威胁。一次性口令、消息摘要,挑战-应答和随机数是增强口令安全的有效方法。请参考本教材内容并查阅有关资料,对这些概念作深入理解。
(2) JDK1.5对目前广泛使用的消息摘要算法,MD4、MD5和SHA-1都提供了支持,在java中实现消息摘要非常简单,java.security.MessageDigest提供了一个简易的操作方法。查阅有关资料,对这一部分作详细了解。
(3)设计一个安全的口令认证方案,并在实验时进行编码实现。三、实验内容
(1)阅读下列程序,分析其运行过程和结果。
register.html//注册页面
<!DOCTYPEHTMLPUBLIC“-//W3C//DTD
HTML4.01Transitional//EN">
<html>
<head>
<title>register.html</title>
</head>
<body><formname="form1"method="post"action="action_reg.jsp">
用户名<inputtype="text"name="username"id="username"/><br/>
密码<inputtype="password"name="password"id="password"/><br/> <inputtype="submit"name="submit"value="提交"/> </form></body></html>action_reg.jsp//注册操作页面<%@pagelanguage="java"import="java.util.*,test.*"pageEncoding="utf-8"%><!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"><html><head><title>MyJSP'action_reg.jsp'startingpage</title>
<metahttp-equiv="pragma"content="no-cache"> <metahttp-equiv="cache-control"content="no-cache"> <metahttp-equiv="expires"content="0">
<metahttp-equiv="keywords"content="keyword1,keyword2,keyword3"> <metahttp-equiv="description"content="Thisismypage"></head><body><%Stringusername=request.getParameter("username");Stringpassword=request.getParameter("password");PersonServiceps=newPersonService();
Personperson=newPerson();Stringpassword_code=ps.Digest(password);//加密if(ps.checkLoginName(username)){if(ps.addPerson(username,password_code)){out.print("注册成功!");}else{out.print("注册失败");}}else{%>
用户名已经存在,<ahref="register.html">请重新注册!</a><%}%></body></html>PersonService.javapackagetest;importjava.util.regex.Matcher;importjava.util.regex.Pattern;importjava.security.MessageDigest;//加密importjava.security.NoSuchAlgorithmException;importjava.util.Random;//随机数importjava.sql.ResultSet;importjava.sql.SQLException;importjava.util.List;importorg.springframework.dao.DataAccessException;importorg.springframework.jdbc.core.RowMapper;publicclassPersonServiceextendsBaseService{//去除空格publicStringreplaceBlank(Stringdigest){Patternp=Ppile("\\s*|\t|\r|\n");Stringstr=digest;Matcherm=p.matcher(str);Stringafter=m.replaceAll("");returnafter;}//通过用户名取得数据publicPersongetPersonByName(Stringusername)
{Stringsql="select*frompersonwhereusername=?"; Personp=null; try{p=jdbcTemplate.queryForObject(sql,newPersonRowMapper(),username); }catch(DataAccessExceptione){ e.printStackTrace(); //Tochangebodyofcatchstatementuse //File|Settings|FileTemplates.} returnp;} //添加数据
publicbooleanaddPerson(Stringusername,Stringpassword){ inti=0; try{Stringsql="insertintoperson(username,password)values(?,?)"; System.out.print(sql); i=this.jdbcTemplate.update(sql,username,password); }catch(DataAccessExceptione){ e.printStackTrace();//TochangebodyofcatchstatementuseFile|Settings|//FileTemplates.} if(i==0) returnfalse; else returntrue;} publicbooleanaddPerson(Personperson){returnaddPerson(person.getUsername(),person.getPassword());} //检测用户名是否存在publicbooleancheckLoginName(Stringusername){ inti=0;try{Stringsql="selectcount(*)frompersonwhereusername=?"; System.out.print(sql); i=this.jdbcTemplate.queryForInt(sql,username); }catch(DataAccessExceptione){ e.printStackTrace();//TochangebodyofcatchstatementuseFile|//Settings|FileTemplates.} if(i==0) returntrue; else returnfalse;} publicbooleancheckLoginName(Personperson){ returncheckLoginName(person.getUsername());}privateclassPersonRowMapperimplementsRowMapper<Person>{publicPersonmapRow(ResultSetrs,intrownum)throwsSQLException{Personperson=newPerson();person.setId(rs.getInt("ID"));person.setUsername(rs.getString("username"));person.setPassword(rs.getString("password"));returnperson;}}//加密
publicStringDigest(Stringpassword)throwsNoSuchAlgorithmException{PersonServiceps=newPersonService();java.security.MessageDigestalga=java.security.MessageDigestgetInstance("SHA-1");alga.update(password.getBytes());byte[]digesta=alga.digest();Stringdigestc=ps.byte2hex(digesta);returndigestc;}//二进制转字符串publicStringbyte2hex(byte[]b){Stringhs="";Stringstmp="";for(intn=0;n<b.length;n++){stmp=(java.lang.Integer.toHexString(b[n]&0XFF));if(stmp.length()==1)hs=hs+"0"+stmp;elsehs=hs+stmp;}returnhs.toUpperCase();}//产生随机数
publicstaticStringgetRandomString(){Stringbase="abcdefghijklmnopqrstuvwxyz0123456789";Randomrandom=newRandom();
StringBuffersb=newStringBuffer();for(inti=0;i<10;i++){intnumber=random.nextInt(base.length());sb.append(base.charAt(number));} returnsb.toString();}}
(2)阅读下列程序,分析其运行过程和结果。
login.jsp//登陆页面,产生服务器随机数,客户端随机数(注:要引入文件jQuery文件——jquery-1.6.min.js)
<%@pagelanguage="java"import="java.util.*,test.*"pageEncoding="utf-8"%>
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
<html>
<head><scriptsrc="js/jquery-1.6.min.js"language="javascript"></script><scriptlanguage="javascript"type="text/javascript">$(function(){$("#password").focusout(function(){//服务器传来数据$.get("getRand.jsp",function(data){$("#serviceRand").html(data);service_Rand=$("#serviceRand").text();$("#service_Rand").val(service_Rand);password=$("#password").val();clickRand=$("#clickRand").val();//$("#serviceRand").empty(); //删除服务器产生的随机数});});});</script><title>MyJSP'login.jsp'startingpage</title>
</head><body><formname="form1"method="post"action="Digest.jsp">
用户名<inputtype="text"name="username"id="username"/><br/>
密码<inputtype="text"name="password"id="password"/><br/> <!--客户端产生的随机数--> <% PersonServiceps=newPersonService(); Stringb=ps.getRandomString(); %> <!--客户端产生的随机数--> <inputtype="hidden"name="clickRand"id="clickRand"value="<%=b%>"/> <!--服务器产生的随机数--> <inputtype="hidden"name="service_Rand"id="service_Rand"/><br/> <inputtype="submit"name="submit"value="提交"/> </form>
服务器产生随机数:<divid="serviceRand"></div>
客户端产生随机数:<br><%=b%></body></html>getRand.jsp//产生服务器随机数<%@pagelanguage="java"import="java.util.*,test.*"pageEncoding="utf-8"%><!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"><html><head><title></title></head><body><%PersonServiceps=newPersonService();
Stringa=ps.getRandomString();//服务器产生的随机数
session.setAttribute("rand",a);//创建sessionout.println(a);%></body></html>Digest.jsp//对密码进行加密,对客户端随机数+服务器端随机数+密码进行加密<%@pagelanguage="java"import="java.util.*,test.*"pageEncoding="utf-8"%><!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"><html>
<head><title>MyJSP'Digest.jsp'startingpage</title></head><body><%Stringusername=request.getParameter("username");StringclickRand=request.getParameter("clickRand");//客户端随机数
Stringservice_Rand=request.getParameter("service_Rand");//服务器端随机数
Stringpassword=request.getParameter("password");//密码
PersonServiceps=newPersonService();Stringb=ps.Digest(password);//加密密码
Stringpassword_total=clickRand+b+service_Rand;Stringa=ps.replaceBlank(password_total);//去空格
Stringc=ps.Digest(a);//加密
out.print("服务器端随机数:"+service_Rand+"<br>");out.print("加密密码:"+b+"<br>");out.print("客户端随机数:"+clickRand+"<br>");out.print("加密后的客户端随机数+服务器端随机数+密码:"+c+"<br>");%><formname="form1"method="post"action="check.jsp"><inputtype="hidden"name="username"id="username"value="<%=username%>
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 麻疹风疹监测工作制度
- 日喀则地区拉孜县2025-2026学年第二学期五年级语文第八单元测试卷(部编版含答案)
- 三明市建宁县2025-2026学年第二学期五年级语文期末考试卷(部编版含答案)
- 临沧地区耿马傣族佤族自治县2025-2026学年第二学期五年级语文第八单元测试卷(部编版含答案)
- 丽江地区宁蒗彝族自治县2025-2026学年第二学期四年级语文期末考试卷(部编版含答案)
- 桂林市荔蒲县2025-2026学年第二学期五年级语文期末考试卷(部编版含答案)
- 折弯机操作工创新方法考核试卷含答案
- 稀土催化材料工保密意识考核试卷含答案
- 汽车货运理货员岗前个人防护考核试卷含答案
- 硅片研磨工岗前岗位操作考核试卷含答案
- 中药饮片GSP培训课件
- 血透患者用药课件
- 2025年省属国企公开招聘备考题库参考答案详解
- 2025年秦皇岛市辅警考试试卷真题带答案
- 泸州市乡镇公务员考试试题及答案
- DB32∕T 5156-2025 零碳园区建设指南
- DB14∕T 3508-2025 公路工程地质勘察监理指南
- 2026年江苏单招职业适应性测试时政经典题集含答案
- 2026年浙江交通职业技术学院单招综合素质考试题库带答案
- 2025年下半年广西日报公开招聘33人笔试参考题库附答案
- 火灾风险隐患排查治理“自知、自查、自改”消防安全管理告知及承诺书
评论
0/150
提交评论