发表于: 2020-05-18 14:53:48

1 1482


今天完成的事情:


修改后完整的注册代码 

@RequestMapping(value = "/register",method = RequestMethod.POST)
public  String register(account account){

logger.info("传入对象为:"+account);

   String u = account.getUsername();
   String p = account.getPassword();

   logger.info("输入的账户为:"+ u+"密码为"+p);

   //判断输入的用户名是否为空 或者  空字符
   if(u!=null && u!=""){

         //判断数据库中是否有此用户名
         account accountA = accountService.findAccount(u);
           //如果查询出的账户为空(代表用户不存在),才能注册
           if(ObjectUtils.isEmpty(accountA)){

             try{

                  //对传入的密码用MD5进行加密加盐
                   String MD5Password = MD5Util.generate(p);

                   //设置密码为新密码
                   account.setPassword(MD5Password);

                   //插入数据
                   int id = accountService.addAccount(account);

                   System.out.print("注册成功,请登录");
                   //返回到登录页面
                   return "loginPage";

                 }catch (Exception e){

                 System.out.print("注册失败,请重新填写注册信息");

                   return "registerPage";
               }

         }else {
System.out.print("用户名已经存在,请更换用户名");
               return "registerPage";
           }

}else{
System.out.print("用户名不能为空");
       return "registerPage";
   }
}

注册流程: 

1.判断输入的用户名密码是否为空  

2.判断数据库中有无此用户

3.对用户密码进行MD5加密加盐,存入数据库中

4.返回到登录页面


完整登录代码   

 @RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(account account, HttpServletResponse response) throws Exception{

logger.info("输入的表格数据为为:" +account);
       String u = account.getUsername();
       String p = account.getPassword();

       logger.info("取出account账号为"+u+"---------"+"取出account密码为"+p);

       //判断输入的用户名是否为空 或者  空字符
       if (u != null && u != "") {

logger.info("用户名通过");

            account accountB = accountService.findAccount(u);

            logger.info("查询出的内容为:"+accountB);

           //判断数据库中是否有此用户名
           if (!ObjectUtils.isEmpty(accountB)) {

logger.info("用户不为空");

               //用MD5验证输入密码有没有被篡改过  没有就返回true
               if(MD5Util.verify(p,accountB.getPassword())==true) {

logger.info("密码正确");

//                    把用户id转化为long类型
                   int BId = accountB.getId();
                   long B = (int)BId;

                   //对此用户id进行des加密
                   String desId = des.encryptFromLong(B);
                   logger.info("对用户id加密的结果为========" + desId);

                   //对当前时间进行des加密
                   String desTime = des.encryptFromLong(System.currentTimeMillis());
                   logger.info("对时间加密的结果为========" + desTime);

                   //对用户id和登陆时间一起进行des加密
                   String token = des.encrypt(desId + "|" +accountB.getUsername()+ "|" + desTime);
                   logger.info("对用户id和登陆时间加密的结果(token)为========" + token);

//                  创建cookie赋值
                   Cookie tokenCookie = new Cookie("token", token);

//                  设置cookie存在时间
                   tokenCookie.setMaxAge(30 * 60);

//                  向客户端返回cookie
                   response.addCookie(tokenCookie);

                   //token放到header头里
//                 response.setHeader("token",token)


                   System.out.print("登陆成功,正在进入主页面");
                   return "redirect:/u/homePage";

               }else {
System.out.print("密码错误,请重新输入");
                   return "loginPage";
               }

} else {
System.out.print("用户不存在,请重新输入用户名");
               return "loginPage";
           }

} else {
System.out.print("用户名不能为空!");
           return "loginPage";
       }

}

登录流程:

1.判断输入用户名密码是否为空

2.判断数据库中有无此用户

3.用MD5工具类验证密码是否被篡改,是否还是相同的密码

4.用des加密用户的id和登陆时间  生成token

5.把token放到cookie里  或者放到reponse的header里

6.进入主页面



拦截器代码

public class LoginInterceptor  implements HandlerInterceptor {

Logger logger = Logger.getLogger(LoginInterceptor.class);
   @Autowired
   accountService accountService;
   
   DESUtilA des = new DESUtilA();
   //在请求之前被调用
   @Override
   public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {

//   请求cookie里的信息,放入cookies
       Cookie[] cookies = httpServletRequest.getCookies();

       //如果cookies的长度等于0,表示没有cookies,返回登录页面,让用户登录一下下,发给用户一个cookie,下次光临的时候用户就有cookie
       if (cookies.length == 0) {
logger.info("没有cookie");

           //如果没有token  就从header里取token
           String token = httpServletRequest.getHeader("token");

           logger.info("header里取出的token"+token);

           //destoken进行解密
           String firstDecrypt = des.decrypt(token);
           logger.info("token进行第一次解密的结果"+firstDecrypt);

           //token解密后的结果根据|进行拆分
           String[] mingwen = firstDecrypt.split("//|");
           logger.info("token解密后的结果根据|进行拆分");

           //token根据 | 拆分出的第一个(用户id
           String TokenId = mingwen[0];
           logger.info("token中解密出第一个是id"+TokenId);
           long id = des.decryptToLong(TokenId);
           logger.info("id解密并转换成long类型"+id);

           //long类型转化为int类型
           int AId = (int)id;

           //根据id查询数据库中有无此用户
           account accountA = accountService.findById(AId);

           //如果用户为空,返回登录界面
           if(accountA == null){
logger.info("没有此token内所含Id的用户,必须去登录");
               httpServletResponse.sendRedirect("/beforeLogin");
               return  false;
           }

//token根据 | 拆分出的第二个(用户名称)  这个不需要验证
           String TokenName = mingwen[1];
           logger.info("token中解密出第二个是名字"+TokenName);

           //token根据 | 拆分出的第三个(用户登陆时间)
           String TokenTime = mingwen[2];
           logger.info("token中解密出第三个是登陆时间"+TokenTime);
           long time = des.decryptToLong(TokenTime);
           logger.info("把时间解密并转换成long类型"+time);

           //把当前时间(long)减去登陆时间(long)  如果>=30分钟   意味着时间已经超过了  返回登录页面
           if (System.currentTimeMillis() - time >= 30 * 60 * 1000) {
System.out.println("token过期=====");
               //返回登录页面
               httpServletResponse.sendRedirect("/beforeLogin");
               return false;
           }

logger.info("tokenid,有效期)验证通过,登录成功");
           return  true;
           //验证某一项

       } else {

//     用户有cookies
           logger.info("cookie");
           //遍历一下用户的cookies,放入cookie,看看他的cookie是什么呀
           for (Cookie cookie : cookies) {
//如果他的cookie与我发给他的cookie相等,就可以直接返到页面里
               if (cookie.getName().equals("token")) {

String Mytoken = cookie.getValue();
                   logger.info("cookie取出的token :" + Mytoken);

                   //destoken进行解密
                   String MingwenA = des.decrypt(Mytoken);
                   logger.info("token进行第一次解密的结果"+MingwenA);

                   //token解密后的结果根据|进行拆分
                   String[] mingwenB = MingwenA.split("\\|");
                   logger.info("token解密后的结果根据|进行拆分后的结果"+mingwenB);

                   //token根据 | 拆分出的第一个(用户id
                   String TokenId = mingwenB[0];
                   logger.info("token中解密出第一个是id"+TokenId);
                   long id = des.decryptToLong(TokenId);
                   logger.info("id解密并转换成long类型"+id);

                   //long类型转化为int类型
                   int BId = (int)id;

                   //根据id查询数据库中有无此用户
                   account accountB = accountService.findById(BId);

                   //如果用户为空,返回登录界面
                   if(accountB == null){
logger.info("没有此token内所含Id的用户,必须去登录");
                       httpServletResponse.sendRedirect("/beforeLogin");
                       return  false;
                   }

//token根据 | 拆分出的第二个(用户名称)
                   String TokenName = mingwenB[1];
                   logger.info("token中解密出第二个是名字"+TokenName);

                   //token根据 | 拆分出的第三个(用户登陆时间)
                   String TokenTime = mingwenB[2];
                   logger.info("token中解密出第三个是登陆时间"+TokenTime);
                   long time = des.decryptToLong(TokenTime);
                   logger.info("把时间解密并转换成long类型"+time);


                   //把当前时间(long)减去登陆时间(long)  如果>=30分钟   意味着时间已经超过了  返回登录页面
                   if (System.currentTimeMillis() - time >= 30 * 60 * 1000) {
System.out.println("token过期=====");
                       //返回登录页面
                       httpServletResponse.sendRedirect("/beforeLogin");
                       return false;
                   }

logger.info("tokenid,有效期)验证通过,登录成功");
                   return  true;
               }
}
}
//        返回登录页面
           httpServletResponse.sendRedirect("/beforeLogin");
           return false;
       }


//在业务处理器处理请求完成之后,生成视图之前执行
   @Override
   public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception{
}
//DispatcherServlet完全处理完请求之后被调用,可用于清理资源
   @Override
   public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception{
}

1. 拦截器内先获取客户端传来的cookie    

2. 如果没有cookie   就从请求头获取token(有cookie就获取其value里的token,然后执行下面的流程)

3.用des解密工具拆分token  (里面是id和登陆时间)

4.根据id查询数据库内有无此用户,无返回false  ,进主页面失败

5. 根据登陆时间查询token是否过期,没有返回false ,进主页面失败

6.上面俩查询都没有返回false  则返回ture   进主页面成功



任务5总结
一    任务进度是否符合预期,是否延期,如果延期,原因是什么,如何避免下次继续延期

任务总耗时7天    完成进度慢

二    脑图分析


三    任务中遇到哪些疑难问题,最终是如何解决的,有哪些值得分享的收获

1. 做任务前要搞清楚登录注册的流程,页面之间互相跳转的关系。

2. 任务中所需的  des是对称加密算法  所以需要一个加密破解方法

    md5是信息摘要算法,是不可逆的,所以需要一个验证密码是否被篡改的方法。

3.拦截器的作用就是拦截用户的请求,从请求头里获取cookie或者session或者token,对其验证后,再决定是否通过。 



自己写的des算法文章:

https://blog.csdn.net/qq_42733162/article/details/106192213



任务GIt代码:https://github.com/git-tianbo/task



深度思考:

  • 1.JWT简单介绍  

 JWT是一个含签名并携带用户相关信息的加密串,页面请求校验登录接口时,请求头中携带JWT串到后端服务,后端通过签名加密串匹配校验,保证信息未被篡改。校验通过则认为是可靠的请求,将正常返回数据。JWT就是一个实现标准规范的Token。

JWT用处:

授权:这是最常见的使用场景,解决单点登录问题。因为JWT使用起来轻便,开销小,服务端不用记录用户状态信息(无状态),所以使用比较广泛;

信息交换:JWT是在各个服务之间安全传输信息的好方法。因为JWT可以签名,例如,使用公钥/私钥对儿 - 可以确定请求方是合法的。此外,由于使用标头和有效负载计算签名,还可以验证内容是否未被篡改。 



JWT组成:

jwt是由3段信息构成的,将这三段信息用.链接到一起就成了jwt字符串。

第一部分称之为头部(header),第二部分称之为载荷(playload),第三部分是签证(signature)。
(1)头部(header)内容:   Head -主要包含两个部分,alg指加密类型,可选值为hs256、ras等等,typ=jwt为固定值,表示token的类型


(2)荷载(playload)内容: 荷载jwt的主体,claims是关于实体(常用的是用户信息)和其他数据的声明


claims有三种类型: registered claims(标准注册声明), public claims(公共声明), and private claims(私有声明)。


registered claims(标准注册声明):

这些是一组预定义的claims,非强制性的,全部属性如下:
iss 【issuer】发布者的url地址
sub 【subject】该JWT所面向的用户,用于处理特定应用,不是常用的字段
aud 【audience】接受者的url地址
exp 【expiration】 该jwt销毁的时间;unix时间戳
nbf 【not before】 该jwt的使用时间不能早于该时间;unix时间戳
iat 【issued at】 该jwt的发布时间;unix 时间戳

jti 【JWT ID】 该jwt的唯一ID编号


Public claims 和 Private claims

这些是自定义的claims,用于传递不同系统间可以共享的数据。
但是,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。

举例:  {"sub": "1234567890","name": "admin","admin": true}


(3)签名(signature)   

把header  和 claims用Base64URL生成的字符  用.连接起来   再加上我们定义的私钥      

 一起进行hs256加密  就生成了签名


sign =   hs256( base64UrlEncode(Header) + "." + base64UrlEncode(Claims) + key)    


最终组成的一个JWT签名: AAA(base64UrlEncode(Header)) . BBB(base64UrlEncode(Claims) . CCC(sign)  


参考: https://www.cnblogs.com/wangshouchang/p/9551748.html



生成JWT的代码   

这里把荷载内容固定了, 如果不想固定的话     定义一个方法传递荷载的参数即可。

public class JWTUtilB {
// 自己定义的私钥
   private static final String SECRET_KEY = "this is a secret key";

   public static void main(String[] args) {
// 生成token
       String jwtToken = Jwts.builder()
// 头部
               .setHeaderParam("typ", "JWT")

// jwt 标注中的申明
               .setIssuedAt(new Date()) // 签发时间
               .setExpiration(new Date(new Date().getTime() + 10000L))// 过期时间
               .setSubject("19930311")// jwt面向的客户
               .setIssuer("huan")// jwt的签发者

               // 公共申明和私有申明
               .claim("user_id", "admin")
              .claim("profession", "前端工程师")
              .claim("age", 25)
              .claim("sex", "")

// 签证
               .signWith(SignatureAlgorithm.HS256, SECRET_KEY.getBytes())

.compact();

       System.out.println("生成的 jwt token 如下:" + jwtToken);




   // 此处是验证生成的jwt
   Jws<Claims> claimsJws = Jwts.parser()
// 验证签发者字段iss 必须是 huan
           .require("iss", "huan")
// 设置私钥
           .setSigningKey(SECRET_KEY.getBytes())
// 解析jwt字符串
           .parseClaimsJws(jwtToken);

   // 获取头部信息
   JwsHeader header = claimsJws.getHeader();
   // 获取载荷信息
   Claims payload = claimsJws.getBody();

   System.out.println("解析过来的jwtheader如下:" + header.toString());
   System.out.println("解析过来的jwtpayload如下:" + payload.toString());

}

}


生成的 jwt token 如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1ODk3ODE4NzUsImV4cCI6MTU4OTc4MTg4NSwic3ViIjoiMTk5MzAzMTEiLCJpc3MiOiJodWFuIiwidXNlcl9pZCI6ImFkbWluIiwicGhvbmUiOiIxODI1MTQyMTAwMCIsImFnZSI6MjUsInNleCI6IueUtyJ9.eOQDXSz7532f0YZnun2qiJMzAKzVxnSGphID5d5cDlY



解析过来的jwt的header如下:

{typ=JWT, alg=HS256}


解析过来的jwt的payload如下:

{iat=1589781875, exp=1589781885, sub=19930311, iss=huan, user_id=admin, profession=前端工程师, age=25, sex=男}


然后根据解析的内容  做判断即可。

2.拦截器、过滤器、监听器各有什么作用? 

过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。
注意:过滤器和拦截器虽然在定义上有区别,但实际上都可以实现过滤拦截的功能
一般使用过滤器做身份认证(判断用户身份),拦截器(过滤器也可以)做权限认证(用户可以做什么)

监听器(Listener):当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程,这就要用到监听器。


三者的作用范围:


参考1: https://blog.csdn.net/c_royi/article/details/80563131

参考2:http://www.r9it.com/20171127/filter-interceptor-lisener.html

3.什么叫明文,什么叫密文,为什么不允许在数据库里明文保存密码? 

明文就是未经过加密的数据,密文是经过加密的数据。

(1)防止拥有查看数据库权限的内部人员    获得用户明文账户密码,恶意泄露。(对内)

(2)一旦数据库发生泄露,攻击者拥有用户的明文密码后,就可以使用用户名和密码去其他网站尝试登陆(因为往往用户会将多个网站的密码根据习惯设成一样的),一旦登陆成功,就会造成更严重的后果。(对外)


4.Cookie的失效时间怎么设定?最大允许存放多少字节?  

cookie.setMaxAge(time)    


maxAge 为正数,表示此cookie从创建到过期所能存在的时间,以秒为单位,此cookie会存储到客户端电脑,以cookie文件形式保存,不论关闭浏览器或关闭电脑,直到时间到才会过期。


maxAge可以为负数,表示此cookie只是存储在浏览器内存里,只要关闭浏览器,此cookie就会消失。maxAge默认值为-1。


maxAge还可以为0,表示从客户端电脑或浏览器内存中删除此cookie。


不同浏览器间每个cookie 文件大小也不同。
Firefox 和safari 是4097 个字节, Opera 是4096 个字节,IE 是4095 个字节   

所以为了更好的兼容各个浏览器,cookie最大别超过4094字节。


5.在App中没有Cookie,怎么解决用户身份识别的问题?Token应该放在什么位置?怎么在后端设计的时候,又支持Cookie,又支持Token?


没有cookie,可以使用token。
token应该放在header,  或者url里(安全系数低,不能泄露url)
后端如何又支持Cookie,又支持Token:
我们都知道 cookie是key-value的形式,可以把token放入cookie中


6.什么叫加盐?加盐能解决什么问题?通常的加盐方式有哪些? 
盐是什么: 盐是一串随机生成字母数字的组合       
加盐是什么:相同的用户可能会设置出一样的密码,那么通过相同的加密算法得到的是相同的结果。大部分常用密码都可以通过MD5摘要反向查询到密码明文。为了防止内部人员(能够接触到数据库或者数据库备份文件的人员)和外部入侵者通过MD5反查密码明文,更好地保护用户的密码和个人帐户安全(一个用户可能会在多个系统中使用同样的密码,因此涉及到用户在其他网站和系统中的数据安全),需要对MD5摘要结果掺入其他信息,称之为加盐。
总结:加盐的目的是为了增加攻击者破解的难度,减少破解了一个人的密码造成多人账户被盗的可能性,保护用户密码。
通常的加密加盐的方式:
1.取出用户密码: 比如 5201314
2.生成随机生成盐: 比如sdsajdjasj898
3.对用户密码+盐进行加密,假设我们用MD5: 

   MD5(5201314+sdsajdjasj898) = sdaqqqqqqqqq44544qqqq(加密加盐的结果)


7. 什么叫MD5,MD5通常做什么用处,为什么MD5不可逆,用做密码加密的时候仍然可能会被解密?


md5是一种信息摘要算法而不是加密算法。 
它可以从一个字符串或一个文件中按照一定的规则生成一个特殊的字符串(这个特殊的字符串就被称之为摘要,我理解就是从文件中摘一些信息片段加工而来),并且一个文件所对应的MD5摘要是固定的,当文件内容变化后,其MD5值也会不一样(虽然理论上来说也有可能会一样,但概率极小),因此,在应用中经常使用MD5值来验证一段数据有没有被篡改。
MD5不可逆的原因是用了散列函数(hash)里面有很多不可逆的运算。
MD5虽然是不可逆的,但是可以通过彩虹码等方式进行破解

所以为了解决MD5安全性不高的问题,我们采取加盐的方式和HMACMD5(加密匙)方式来使用。


8.拦截器是什么?为什么要配置拦截器?拦截器里通常应该校验什么,怎么做到统一配置拦截器,让必须登录才能使用的接口,判断用户未登录时,返回错误信息? 
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。 
拦截器的典型应用就是 AOP,将某些功能以独立切面的形式插入现有的业务流程当中,能够大大减少 Action 的代码。
拦截器通常校验什么:比如判断登录,验证权限,记录日志等
需要在springMvc.xml中配置拦截器   可配置多个。
用来拦截需要登录才能使用的接口,比如我的所有 u/**  的页面需要登录  那就用拦截器拦截它
然后在拦截器类内部 内验证用户cookie或者token的信息,验证成功返回ture可进入页面,验证失败返回false就需要登录。
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<!-- 登录认证拦截器 -->
<mvc:interceptor>
<!--/** 表示所有url包括子url路径 -->
<mvc:mapping path="/u/**"/>
<bean class="com.mb.Interceptor.LoginInterceptor"/>
<!--设置拦截器路径-->
</mvc:interceptor>


9.Https是什么?怎么配置Https证书,哪些请求需要Https,登录是否需要Https?  


HTTP协议传输的数据都是未加密的,因此使用HTTP协议传输隐私信息非常不安全。为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议更为安全。



HTTPS需要一个由CA认证的证书,CA的作用就是提供证书以及证书运维相关服务。任何个体/组织都可以扮演 CA 的角色,只不过难以得到客户端的信任,一般浏览器都有默认信任的CA厂商。
如果未使用证书、使用的证书没有签证,或者未在浏览器受信的 CA 签证,浏览器会提示你连接不安全。
证书由域名、公司信息、序列号和签名信息组成,当我们通过 HTTPS 访问页面时,浏览器会主动验证证书信息是否匹配,也会验证证书是否有效。
通常来说,SSL 证书分为三大类,他们的安全性是递增的,当然价格也是成正比的。
DV (Domain Validation Certificate) DV 证书适合个人网站使用,申请证书时,CA 只验证域名信息。几分钟之内就能签发。
OV ( Organization Validation Certificate) OV 证书需要认证公司的信息。1-2天签发。
EV ( Extended Validation Certificate) EV 证书的认证最为严格,一般会要求提供纸质材料。签发时间也较久。

云服务器的申请方式。  参考: https://www.cnblogs.com/ggband/p/10169619.html


对于一些敏感数据的请求,应该要用到https。    

登录设计到用户的账户密码,为了保密安全,最好用HTTPS。 


10.什么是对称加密,什么是非对称加密?分别适用于什么场景?  

(1)对称加密
对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密。对称加密只有一个秘钥,作为私钥。
因为是用的一个密钥,所以效率很高
适用场景: 保密性要求不高,请求频繁的业务。
缺点:因为是用的一个密钥,一旦密钥被黑客拦截,信息就不安全了。
常见的对称加密算法:DES,AES,3DES等等。
(2)非对称加密
非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。私钥永远在自己手里,非常安全,黑客拦截也没用,因为私钥未公开。
适用场景: 保密性要求很高的业务。
缺点:效率比对称加密要慢些。

常见的非对称加密算法:RSA,ECC


11.Token的构造规则是什么,怎么确认用户身份的,怎么保证Token被偷窃的问题?  


在不使用JWT标准生成Token的情况下,Token的构造规则是自定义的。
但自定义的Token中必须要有用户的某个身份信息,比如用户id(用来查库,确认用户身份)  及Token生成时间(判断此Token是否到期),其他内容随意。 

可以用DES对Token关键信息一起进行加密,拿到Token后再进行解密。从而保证Token的安全性。


12. Cookie是在Http的什么位置存放,Cookie里的键可以重复吗?  


Cookie相关的Http头,有两个Http头部和Cookie有关:Set-Cookie和Cookie。
Set-Cookie由服务器发送,它包含在响应请求的头部中,用于在客户端创建一个Cookie。
Cookie头由客户端发送,包含在HTTP请求的头部中。只有cookie的domain和path与请求的URL匹配才会发送这个cookie。

Cookie里的键不能重复,不然第二个相同的key会把前一个key的value覆盖掉。  


13.什么是session?什么是cookie?session和cookie有什么区别?什么场景适用于session?什么场景适用于cookie?  


cookie数据是存放在客户的浏览器上,session数据是放在服务器上。


cokie: 由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道用户身份。而且HTTP协议数据一旦交互完毕,客户端与服务器端的连接就会关闭,意味着服务器无法从连接上跟踪对话。怎么办呢?那就给客户端们颁发一个密匙吧,每人一个,无论谁访问都必须携带自己密匙。这样服务器就能从密匙上确认客户身份了。这就是Cookie的工作原理。


session:  Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。


使用场景: 由于session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

由于cookie不是很安全 ,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。

可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。


参考: https://www.cnblogs.com/endlessdream/p/4699273.html


明天计划的事情:

开始任务6



返回列表 返回列表
评论

    分享到