发表于: 2019-11-13 21:28:24

1 997


今天完成的事情:

修改了head里的信息,增加了登录和不登录时的样式

修改一下拦截器的逻辑,当没有登录状态时点击职业页面返回到登录页面

添加一个JWT工具类

public class JwtUtil {
public static String createJWT(long ttlMillis,String userName,String userPwd){
//指定签名的时候使用的签名算法,也就是header那部分,jwt已经将这部分内容封装好了。
       SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

       //生成JWT的时间
       long nowMillis = System.currentTimeMillis();
       java.util.Date now = new java.util.Date(nowMillis);

       //创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
       //本例子为使用用户名和密码进行验证
       Map<String,Object> claims = new HashMap<>();
       claims.put("name",userName);
       claims.put("pwd",userPwd);


       //生成签名的时候使用的秘钥secret,这个方法本地封装了的,一般可以从本地配置文件中读取,切记这个秘钥不能外露哦。它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

       /* byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Secret);
       Key key = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());*/

       String key = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";
       //生成签发人
       String subject = userName;

       //下面就是在为payload添加各种标准声明和私有声明了
       //这里其实就是new一个JwtBuilder,设置jwtbody
       JwtBuilder builder = Jwts.builder()
//如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builderclaim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
               .setClaims(claims)
//设置jti(JwtUtil ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
               .setId(UUID.randomUUID().toString())
//iat: jwt的签发时间
               .setIssuedAt(now)
//代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可以存放什么useridroldid之类的,作为什么用户的唯一标志。
               .setSubject(subject)
//设置签名使用的签名算法和签名使用的秘钥
               .signWith(signatureAlgorithm,key);
       if (ttlMillis >= 0){

long expMillis = nowMillis+ttlMillis;
           java.util.Date exp = new Date(expMillis);
           //设置过期时间
           builder.setExpiration(exp);
       }

//生成JWT
       return  builder.compact();
   }

/**
    * Token的解密
    * @return
    */
   public static Claims parseJWT(String token){
//签名秘钥,和生成的签名的秘钥一模一样
       String key = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";

       Claims claims = Jwts.parser()
//设置签名的秘钥
               .setSigningKey(key)
//设置需要解析的jwt
               .parseClaimsJws(token).getBody();
       return claims;
   }

/**
    * 校验token中密码是否相同
    * @param token
    * @param user
    * @return
    */
   public static Boolean isVerify(String token, User user){
//签名秘钥,和生成的签名的秘钥一模一样
       String key = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";

       //得到DefaultJwtParser
       Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token).getBody();
       if(claims.get("pwd").equals(user.getPwd())){
return true;
       }
return false;
   }
}

解决了没有登录时查看职业页面跳转500错误的问题

这里使用JWT代替了token

用token放进了时间名字和ID并进行了加密,那在其他页面把cookie取出来,解密token,对字符串进行截取就能完成在头部上显示用户名字的要求。

需要登录才能查看的页面

主页因为没有登录的时候是没有token的,所以需要在截取字符串的时候做判断

明天计划的事情:

开始任务六

遇到的问题:

没有token查看职业页面条转500错误,修改拦截器的逻辑,判断没有token时跳转到登录页面


个人脑图


任务深度思考

1.JWT简单介绍 

什么是JWT

JWT简称json web token

是为了在网络应用环境中传递声明而执行的一种基于json的开放标准。特别适合分布式站点的单点登录场景。jwt的声明一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息,以便于从服务器获取资源,也可以增加一些额外的其他业务逻辑所用到的生命信息。

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

第一部分称之为头部(header),第二部分称之为载荷(playload),第三部分是签证(signature)。

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

过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。

拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。

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

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

1)明文是加密之前的文字,密文是加了密的的文字。密文是对明文进行加密后的报文

(2)不允许在数据库里明文保存密码:

(一)用明文保存密码有很大的信息安全隐患。

(二)一般数据库里还存有用户的姓名、手机号、用户名等信息,

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

常用加密方式:MD5-----一般用来做验证,防止篡改;DES--------对称加密;RSA--------非对称加密

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

Cookie 失效:cookie.setMaxAge(time)。0表示立即销毁cookie,-1表示关闭浏览器cookie就失效,大于1是设置的销毁时间,单位是秒,例如1小时后销毁,就是60*60。

百度搜到好像是4K。

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

App 中没Cookie的话,可以使用token,而且基本可解决跨站攻击,比如中间人伪造Cookie,或者前端中出现的跨域认证。 Token 一般放在请求的头部,也就是header。后端设计:我们都知道 cookie是key-value的形式,可以把token放入cookie中

6.什么叫加盐?加盐能解决什么问题?通常的加盐方式有哪些?

不同的用户可能会设置出一样的密码,那么通过相同的加密算法得到的是相同的结果。大部分常用密码都可以通过MD5摘要反向查询到密码明文。为了防止内部人员(能够接触到数据库或者数据库备份文件的人员)和外部入侵者通过MD5反查密码明文,更好地保护用户的密码和个人帐户安全(一个用户可能会在多个系统中使用同样的密码,因此涉及到用户在其他网站和系统中的数据安全),需要对MD5摘要结果掺入其他信息,称之为加盐。

简单的说就是为了减少破解了一个人的密码造成多人账户被盗的可能性。

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

什么是MD5

它是一种信息摘要算法,它可以从一个字符串或一个文件中按照一定的规则生成一个特殊的字符串(这个特殊的字符串就被称之为摘要,我理解就是从文件中摘一些信息片段加工而来),并且一个文件所对应的MD5摘要是固定的,当文件内容变化后,其MD5值也会不一样(虽然理论上来说也有可能会一样,但概率极小极小),因此,在应用中经常使用MD5值来验证一段数据有没有被篡改。比如,在数据的发送方将原始数据生成出MD5值,然后把原始数据连同其MD5值一起传给接收方,接收该收到数据后,先将原始数据用MD5算法生成摘要信息,然后再将此摘要信息与发送方发过来的摘要信息进行比较,如果一致就认为原始数据没有被修改,否则原始数据就是被修改过了。

MD5的几个特点:

1、它是一段固定长度的数据,即128bit的由“0”和“1”组成的一段二进制数据。无论原始数据是多长或多短,其MD5值都是128bit。

2、通常(或者叫行业规定),这段128bit的数据,按4bit一组分成32组,每一组按16进制来计算其值,并以字符的形式输出每个值。比如一组数据按16进制计算出来的值是0~9,打印出来也是0~9,如果计算出来的值是a~f,如果直接打印的话将会是10~15,在java中通常使用Integer.toHexString(int)方法来将16进制的 a~f 打印成字母“a~f”,最终这个128bit的数据将会被打印成一个32位的字符串。所以我们通常所说的MD5值就是指这串32位的由“0~9,a~f”所组成的字符串。如果你看到某个MD5不是32位,或发现其中含有“0~f”之外的字符,那肯定是个错误的MD5值。

3、确定性,一个原始数据的MD5值是唯一的,同一个原始数据不可能会计算出多个不同的MD5值。

4、碰撞性,原始数据与其MD5值并不是一一对应的,有可能多个原始数据计算出来的MD5值是一样的,这就是碰撞。

5、不可逆。也就是说如果告诉你一个MD5值,你是无法通过它还原出它的原始数据的,这不是你的技术不够牛,这是由它的算法所决定的。因为根据第4点,一个给定的MD5值是可能对应多个原始数据的,并且理论上讲是可以对应无限多个原始数据,所有无法确定到底是由哪个原始数据产生的。

8.拦截器是什么?为什么要配置拦截器?拦截器里通常应该校验什么,怎么做到统一配置拦截器,让必须登录才能使用的接口,判断用户未登录时,返回错误信息?

拦截器:是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,比如AOP就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。拦截器的检验:一般是请求地址,用户信息等。

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

https:是以安全为目标的http通道,简单讲是http的安全版,https的安全基础是ssl证书,因此加密的详细内容就需要ssl证书。https协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。配置Https要有域名,而域名要备案的,所以等买域名再说。Https加密用的,所以登录应该是尽可能使用https。

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

对称加密又称公开密钥加密,加密和解密都会用到同一个密钥,如果密钥被攻击者获得,此时加密就失去了意义。常见的对称加密算法有DES、3DES、AES、Blowfish、IDEA、RC5、RC6。

非对称加密又称共享密钥加密,使用一对非对称的密钥,一把叫做私有密钥,另一把叫做公有密钥;

公钥加密只能用私钥来解密,私钥加密只能用公钥来解密。

常见的公钥加密算法有:RSA、ElGamal、背包算法、Rabin(RSA的特例)、迪菲-赫尔曼密钥交换协议中的公钥加密算法、椭圆曲线加密算法)。

适用场景:DES/AES等对称加密:速度快,适合大量数据,处理数据后可复原。

RSA等非对称加密:身份验证,数据签名等数据量小的地方,比如:ssh口令登录,ssh公钥登录

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

请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token revocataion可以使一个特定的token或是一组有相同认证的token无效。

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

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

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

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

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

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



返回列表 返回列表
评论

    分享到