认证授权

317 阅读5分钟

认证和授权

  • 认证(Authentication): 你是谁,通过验证您的身份凭据(例如用户名/用户ID和密码),系统得以知道你就是你,也就是说系统存在你这个用户。
  • 授权(Authorization):你有权限干什么,掌握了访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问。

Cookie

Cookie是为了辨别用户信息而存储在本地终端的数据。存放在客户端,一般保存用来保存用户信息。

作用:

  1. 保存已经登录过的用户信息
  2. 保存Session或者Token,请求的时候会带上Cookie,这样后端就可以获取到Session或者Token了
  3. 用来记录和分析用户行为
  • 设置Cookie
@GetMapping("addCookie")
public String addCookie(HttpServletResponse response){
    Cookie cookie = new Cookie("username", "pluto");
    // 过期时间1天
    cookie.setMaxAge(24 * 60 * 60);
    response.addCookie(cookie);
    return "ok";
}

  • 获取Cookie
@GetMapping("getCookie")
public String getCookie(@CookieValue(value = "username", defaultValue = "tong") String username){
    return "cookie(username) value is : " + username;
}

Session

Session的主要作用就是通过服务端记录用户的状态。Cookie将数据保存在客户端(浏览器端),Session将数据保存在服务器端。相对来说Session安全性更高。如果使用Cookie的一些敏感信息不要写入Cookie中,最好能将Cookie信息加密然后使用到的时候再去服务器端解密。

Session进行身份验证:

  1. 用户向服务器发送用户名和密码用于登陆系统。
  2. 服务器验证通过后,服务器为用户创建一个Session,并将Session信息存储起来。
  3. 服务器向用户返回一个sessionId,写入用户的Cookie。
  4. 当用户保持登录状态时,Cookie将与每个后续请求一起被发送出去。
  5. 服务器可以将存储在Cookie上的sessionId与存储在内存中或者数据库中的Session信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。
@GetMapping("getSession")
public String getSession(HttpServletRequest request, HttpServletResponse response){
    HttpSession session = request.getSession();
    session.setAttribute("3568121212", "tong");
    // Session有效时间(秒) 一个小时
    session.setMaxInactiveInterval(60 * 60);
    System.out.println(session.getMaxInactiveInterval());
    Cookie cookie = new Cookie("sessionId", "3568121212");
    // 过期时间1天
    cookie.setMaxAge(24 * 60 * 60);
    response.addCookie(cookie);
    return "ok";
}

@GetMapping("getUser")
public String getUser(HttpServletRequest request, HttpServletResponse response){
    HttpSession session = request.getSession();
    Optional<Cookie> first = Arrays.stream(request.getCookies()).
    			filter(cookie -> "sessionId".equals(cookie.getName())).findFirst();
    Object attribute = session.getAttribute(first.get().getValue());
    System.out.println(attribute);
    return "ok";
}

Session缺陷

  1. 需要我们保证保存Session信息服务器的可用性
  2. 不适合移动端(依赖Cookie)等等

Cookie无法防止CSRF攻击

CSRF(Cross Site Request Forgery)一般被翻译为 跨站请求伪造

当我们通过Session认证的时候,我们一般使用Cookie来存储sessionId,当我们登陆后后端生成一个sessionId放在Cookie中返回给客户端,服务端通过Redis或者其他存储工具记录保存着这个sessionId,客户端登录以后每次请求都会带上这个sessionId,服务端通过这个sessionId来标识你这个人。如果别人通过Cookie拿到了sessionId后就可以代替你的身份访问系统了。所以,当你点击其他链接的时候,就会将自己的Cookie信息暴露给别人,别人就可以拿到sessionId信息。

Token

JWT(JSON Web Token),这种方式服务器端就不需要保存Session数据了,只用在客户端保存服务端返回给客户的Token就可以了,扩展性得到提升。JWT 本质上就一段签名的JSON格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。

JWT由三部分构成:

  1. Header(头部):描述JWT的元数据。定义了生成签名的算法以及Token的类型,通常是一个JSON对象

    {   
        "alg": "SHA256" // 算法类型,这里默认是SHA256
        "typ": "JWT"  // Token类型,这里统一为JWT
    }
    
  2. Payload(负载):用来存放实际需要的数据,Payload也是一个JSON对象,官方定义了一些字段,还可以自己定义一些字段

    • iss (issuer):签发人
    • exp (expiration time):过期时间
    • sub (subject):主题
    • aud (audience):受众
    • nbf (Not Before):生效时间
    • iat (Issued At):签发时间
    • jti (JWT ID):编号
  3. Signature(签名):服务器通过Payload、Header和一个密钥(secret)使用Header里面指定的签名算法(默认是HMAC SHA256)生成

    • 签名算法:HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
    • Token: 把Header、Payload、Signature三个部分拼成一个字符串,每个部分之间用"点"(.)分隔

数据格式,由逗号分隔成三部分:

在基于Token进行身份验证的的应用程序中,服务器通过Payload、Header和一个密钥(secret)创建令牌(Token)并将 Token 发送给客户端,客户端将Token保存在Cookie或者localStorage里面,以后客户端发出的所有请求都会携带这个令牌。你可以把它放在Cookie里面自动发送,但是这样不能跨域,所以更好的做法是放在HTTP Header的Authorization字段中: Authorization: Bearer Token

JWT身份验证

  1. 用户向服务器发送用户名和密码用于登陆系统。
  2. 身份验证服务响应并返回了签名的 JWT,上面包含了用户是谁的内容。
  3. 用户以后每次向后端发请求都在Header中带上 JWT。
  4. 服务端检查 JWT 并从中获取用户相关信息。