Java——项目常用登录方式详解

目录标题

  • 一、6种登录方式
    • 1. Cookie-Session 认证
    • 2. 基于 Cookie-Session 的改造认证
    • 3. Token认证
    • 4. 基于Token的JWT认证
    • 5. SSO单点登录
    • 6. OAuth第三方登录
  • 二、 总结
  • 三、 JWT登录案例:

一、6种登录方式

1. Cookie-Session 认证

早期互联网以 web 为主,客户端是浏览器,所以 Cookie-Session 方式最那时候最常用的方式,直到现在,一些 web 网站依然用这种方式做认证。
认证过程大致如下:

用户输入用户名、密码或者用短信验证码方式登录系统;
服务端验证后,返回一个 SessionId [SessionId与用户信息进行关联,通过SessionId可以得到用户信息],客户端将 SessionID 存到 cookie,下次访问的时候带着SessionID;
当客户端再发起请求,自动带上 cookie 信息,服务端通过 cookie 获取 Session 信息进行校验,判断对应用户是否存在;

弊端

只能在 web 场景下使用,如果是 APP 中,不能使用 cookie 的情况下就不能用了;
即使能在 web 场景下使用,也要考虑跨域问题,因为 cookie 不能跨域;
cookie 存在 CSRF(跨站请求伪造[前后端分离的项目])的风险;
如果是分布式服务做了集群,第一次登录请求访问的是A服务,第二请求来到了B服务,B服务就没有第一次请求访问登录得到的Session Id. 此时还需要考虑 Session 同步问题;

2. 基于 Cookie-Session 的改造认证

由于传统的 Cookie-Session 认证存在诸多问题,可以把上面的方案改造一下。改动的地方如下:

不用 cookie 做客户端存储,改用其他方式,web 场景下让前端使用 local storage(局部存储器。它是html5新增的一个本地存储API),APP 中使用客户端数据库,这样就实现了跨域,并且避免了 CSRF ;
服务端也不存 Session 了,把 Session 信息拿出来存到 Redis 等内存数据库中,这样即提高了速度,又避免了 Session 同步问题;

经过改造之后变成了如下的认证过程:

用户输入用户名、密码或者用短信验证码方式登录系统;
服务端经过验证,将认证信息构造好的数据结构存储到 Redis 中,并将 key 值返回给客户端;
客户端拿到返回的 key,存储到 local storage 或本地数据库;
下次客户端再次请求,把 key 值附加到 header 或者 请求体中;
服务端根据获取的 key,到 Redis 中获取查询相关value得到认证信息;

弊端:

可能存在单点故障的问题,redis宕机后,全部用户都得重新登录。
redis可以做集群解决单点故障问题。但回过头来一想, 就为了这小小的session我还得为他付出这么多精力,得不偿失。
也会占用redis的内存,用户多的话,要占很多redis内存。

3. Token认证

例子:token认证
认证过程大致如下:

用户在登录表单中输入用户名和密码,然后点击登录。
请求通过在请求头中携带token发送登录请求之后,通过在后端查询数据库验证用户的合法性。【通常会让用户表与token有关联关系,一般还会对token加密,而且还会设置过期时间。所以一般采用redis来存储,key存token,值存用户相关信息】
在每次发送访问请求时提供token信息(一般是服务器采用filter过滤器或拦截器来判断),然后根据这个token得到相关用户信息(如:用户id)去数据库查得到用户信息进行验证账号密码等,通过则让用户访问服务端接口,不通过则拒绝访问。

弊端:

这一切其实和session id没有本质区别。
需要用token去数据库查询是否有相应用户。
也会占用redis的内存,用户多的话,要占很多redis内存。

4. 基于Token的JWT认证

JWT:Json web token 是为了在网络应用环境间传递声明而执行的一种基于JSON传输格式的开放标准,可实现无状态、分布式的Web应用授权。
先说缺点:
使用JWT时,有个十分头疼的问题。用户主动注销,服务器不能让token主动失效。就是说token没有过期前,你想让它提前停止使用,不好意思没得办法。
解决思路有几种,不过都不是很完美。要么你就不解决JWT退出登录的问题,你在设置对token设置过期的时候,不要设置太久,设置1天,1天过后就失效。

认证过程大致如下:

用户登陆服务器,服务端验证用户账号密码,使用secret生成JWT令牌【一般还会设置过期时间,在生成token的时候指定】,然后将令牌返回给客户端。
客户端访问服务端的时候,在请求头中带上这个令牌,服务端使用secret去验证令牌是否合法,合法则让用户访问服务器接口,不合法则拒绝。
服务器并不保存token,就不用像上述方式,拿到token还得去redis数据库验证,根据token得到对应值(一般时用户的id,拿到用户id后,去数据库查用户信息,得到账号密码进行校验)。(注意理解这里,因为生成的JWT令牌(是按照某种规则生成的,==它可以包含用户信息,比如我们把用户id或带有权限标识的用户JSON数据[做权限校验]存到JWT令牌,他第二次带着JWT令牌登录时,解析JWT令牌得到他的用户id,此时拿着用户id去查询那个用户信息,得到账号密码进行校验=。))。

JWT令牌结构:

Header(头部)        是token的一部分,用来存放token的类型和编码方式,通常是使用base-64编码
Payload(负载)       包含了信息,你可以存放任一种信息,比如用户信息,产品信息等,它们都是使用base-64编码方式【编码方式取决于你在Header中设置的编码方式】进行存储
Signature(签名)     包括了header,payload和密钥的混合体,密钥必须安全地保存储在服务端

发送给服务器的令牌样子是AAAA(头部).BBBB(负载).CCCC(签名)的形式。

Header:
通常由两部分组成,令牌的类型与所使用的签名算法。它会被Base64编码编成JWT结构的第一部分。【Base64编码:不是一种加密,就是一种编码,它能被解码】

{
“alg”:“HS256”, // 签名算法 默认 HS256
“typ”:“JWT” // 令牌的类型 默认 JWT
}
Payload:
用于包含声明信息,一般用来声明用户数据。它会被Base64编码编成JWT结构的第二部分。【Base64编码:不是一种加密,就是一种编码,它能被解码】
因为能被解密,所以这里面不要放特别敏感的用户信息。

{
“name”:“zhangsan”,
“age”:23,
“email”:“[email protected]
}
Signature:
他是基于Header,Payload被Base64编码后加上我们提供的一个私钥,这个私钥只有服务端知道,然后就会将3者使用Header里面指定的签名算法进行签名生成JWT。
作用:保证JWT没有被篡改。

token = ${base64UrlEncode(header)}.${base64UrlEncode(payload)}.signature)

5. SSO单点登录

常基于OAuth2.0 实现SSO单点登录

传送地址:添加链接描述

6. OAuth第三方登录

OAuth2.0 : 使用第三方应用授权的令牌,进行身份信息获取。再去访问另一个产品时,可以不用再登录,即可获取登录状态。
最经典例子:在网页上留言,使用微信授权登录。

二、 总结

Cookie + Session 历史悠久,适合于简单的后端架构,需开发人员自己处理好安全问题。
基于Token的JWT 方案对后端压力小,适合大型分布式的后端架构,但已分发出去的 token ,如果想收回权限,就不是很方便了。
SSO 单点登录,适用于中大型企业,想要统一内部所有产品的登录方式。
OAuth 第三方登录,简单易用,对用户和开发者都友好,但第三方平台很多,需要选择合适自己的第三方登录平台

三、 JWT登录案例:

基于自定义注解+拦截器实现(没有指定过期时间):添加链接描述
基于自定义注解+拦截器实现(指定过期时间):添加链接描述
设置过期时间:添加链接描述

如何让token失效:添加链接描述

你可能感兴趣的:(java,redis,数据库)