Web应用程序的身份验证:Session认证、Token认证

这篇具有很好参考价值的文章主要介绍了Web应用程序的身份验证:Session认证、Token认证。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、Web应用程序的身份验证

1、Session认证

① 用户向服务器发送用户名和密码

② 服务器验证通过后,在当前对话(session)里面保存相关数据,如用户角色,登陆时间等

③ 服务器向用户返回一个session_id,写入用户的Cookie

④ 用户随后的每一次请求,都会通过Cookie,将session_id传回服务器

⑤ 服务器收到session_id,找到前期保存的数据,由此得知用户的身份

认证流程:

Web应用程序的身份验证:Session认证、Token认证

 

        Session认证的方式扩展性不好,如果是服务器集群,或者是跨域的服务导向架构,就要求session数据共享,以便每台服务器都能够读取session,针对这问题有两种解决方案:

        ① session数据持久化,写入数据库或别的持久层。优点是架构清晰,但工程量大

        ② 服务器不再保存session数据,所有数据都保存在客户端,每次请求都发回服务器。Token就是其中一个代表

2、Token认证

Token是在服务端产生的一串字符串,是客户端访问资源接口(API)时所需要的资源凭证

        ① 客户端使用用户名和密码请求登陆,服务端收到请求,去验证用户名和密码

        ② 验证成功后,服务端会签发一个token并把这个token发送给客户端

        ③ 客户端收到token后,存储起来,比如放在cookie或者localStorage里头

        ④ 客户端每次向服务端请求资源时需要带上这个token

        ⑤ 服务端收到请求后去验证这个token,成功则返回请求数据

Web应用程序的身份验证:Session认证、Token认证

 

实现方式:JWT(JSON Web Token)认证

原理:

① 用户发送用户名和密码后,服务器认证并生成JWT令牌(JSON对象),将其发回给客户端

 (为了防止用户篡改数据,服务器在生成这个对象的时候会加上签名)

② 客户端将JWT令牌存储在本地以便后续使用

③ 当客户端向另一个域名服务器发送请求时,将JWT令牌作为请求头(放在Authorization字段里头)或请求参数发送

④ 服务器收到请求后,检查JWT令牌的有效性,并进行身份验证和授权

⑤ 若令牌有效则返回请求的数据,否则返回未授权的错误信息

JWT由三个部分组成:

1、Header(头部):

{
  "alg": "HS256", // 令牌类型
  "typ": "JWT" //加密算法 
}

2、Payload(负载):

{
  "iss": "example.com",
  "sub": "1234567890",
  "aud": ["foo", "bar"],
  "exp": 1648696800,
  "nbf": 1648693200, // 2022年4月29日10:20:00
  "iat": 1648694700,
  "jti": "abcdef123456"
}
// 1、iss(issuer): 表示JWT签发者的名称,通常是一个字符串或URL。
// 2、sub(subject): 表示JWT的主题,即客户端的唯一标识符,通常是一个用户ID。
// 3、aud(audience): 表示JWT的预期接收者,即对该JWT有效的接收方,可以是单个字符串或一个字符串数组。
// 4、exp(expiration time): 表示JWT的过期时间,用Unix时间戳表示。
// 5、nbf(not before): 表示JWT的生效时间,用Unix时间戳表示。
// 6、iat(issued at): 表示JWT的签发时间,用Unix时间戳表示。
// 7、jti(JWT ID): 表示JWT的唯一标识符,通常用于避免重放攻击。

3、Signature(签名):由Header、Payload和一个密钥(secret,存储在服务器端,对外不可见)进行签名生成。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

将Header、Payload和Signature通过'.'连接在一起形成JWT令牌,例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

代码实现:

① 引入依赖

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

② 添加JWT配置

# JWT相关配置
jwt.secret=your-secret
jwt.expiration=3600

③ 创建JWT工具类:用于生成和解析JWT

@Component
public class JwtUtils {
​
    // 秘钥
    @Value("${jwt.secret}")
    private String secret;
​
    // 过期时间,单位秒
    @Value("${jwt.expiration}")
    private Long expiration;
​
    // 生成JWT
    public String generateToken(Long userId) {
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes()); // 创建密钥
        Date now = new Date();
        Date expireTime = new Date(now.getTime() + expiration * 1000);
        return Jwts.builder()
                .setIssuer("issuer") // 设置JWT的签发者
                .setAudience("audience") // 设置JWT的接收方
                .setSubject(userId.toString()) // 设置JWT的主题
                .setIssuedAt(now) // 设置JWT的签发时间
                .setExpiration(expireTime) // 设置JWT的过期时间
                .signWith(key, SignatureAlgorithm.HS256) // 用HS256算法和密钥key签名JWT
                .compact(); // 生成JWT字符串
    }
​
    // 解析JWT
    public Claims parseToken(String token) {
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes()); // 创建密钥
        return Jwts.parserBuilder()
                .setSigningKey(key) // 设置用于解析JWT的密钥
                .build()
                .parseClaimsJws(token) // 解析JWT,获取Jws<Claims>实例
                .getBody();
    }
}
 

④ 配置拦截器:用于验证请求中的JWT是否有效

@Component
public class JwtInterceptor implements HandlerInterceptor {
​
    @Autowired
    private JwtUtils jwtUtils;
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从请求头中获取token
        String token = request.getHeader("Authorization");
        // 判断token是否存在并以Bearer开头
        if (token != null && token.startsWith("Bearer ")) { 
            token = token.substring(7); // 去掉token前缀
            Claims claims = jwtUtils.parseToken(token); // 解析JWT
            if (claims != null) {
                Long userId = Long.valueOf(claims.getSubject()); // 获取JWT中的用户id
                // 将用户信息存储到request中,方便后续操作
                request.setAttribute("userId", userId);
                return true;
            }
        }
        // 解析失败,返回401未授权状态码
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        return false; // 拦截请求
    }
}

⑤ 使用JWT

@RestController
@RequestMapping("/api")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody UserLoginDto userLoginDto) {
        // 用户登录逻辑
    
        // 生成 JWT token
       String token = Jwts.builder()
            .setSubject(user.getUsername()) // 主题
            .claim("roles", user.getRoles()) 
            .setIssuedAt(new Date()) // 签发时间
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 过期时间
            .signWith(SignatureAlgorithm.HS512, SECRET_KEY) // 使用算法和密钥对token进行签名。
            .compact(); // 将JWT token生成为字符串
    
       // 返回 token 给客户端
       return ResponseEntity.ok(new AuthResponse(token));
    }
​
    
    @GetMapping("/users")
    @PreAuthorize("hasAuthority('ROLE_ADMIN')") // 拥有 ROLE_ADMIN 权限的用户才能访问该方法
    public ResponseEntity<?> getUsers(@RequestHeader("Authorization") String    authorizationHeader) {
        String token = authorizationHeader.substring(7); // 去掉 "Bearer" 前缀
    
        // 验证 token 是否有效
        Claims claims = Jwts.parser() // 获取一个JwtParser对象
                .setSigningKey(SECRET_KEY) // 设置JWT的签名密钥,用于校验JWT的合法性
                .parseClaimsJws(token) // 将其转化为Jws对象
               .getBody(); // 获取Jws对象中的payload信息
    
        // 获取用户列表逻辑
}
​
    
    @GetMapping("/users/{id}")
    public ResponseEntity<?> getUserById(@PathVariable Long id) {
        // 根据用户ID获取用户信息逻辑
    }
    
    // 省略其他接口...
}
 

Session和Token认证的区别:

        Session和Token都是常用的用户认证方式,它们的作用都是为了验证用户身份和授权访问资源,但是它们的实现方式有所不同。

        Session是一种服务器端认证方式,通常通过在服务器端保存用户的登录信息(较安全),以便在后续的请求中进行验证。当用户进行登录操作时,服务器会创建一个Session,并给这个Session分配一个唯一的标识符(Session ID),然后将这个Session ID发送给客户端保存。客户端在后续的请求中需要携带这个Session ID,服务器端根据这个Session ID来查找对应的Session,从而验证用户的身份。

        Token是一种无状态认证方式,通常通过在客户端保存用户的登录信息(不安全),以便在后续的请求中进行验证。当用户进行登录操作时,服务器会生成一个Token,并将这个Token发送给客户端保存。客户端在后续的请求中需要携带这个Token,服务器端通过验证这个Token来确定用户的身份。

优缺点:

        Session需要在服务器端保存用户的登录信息,因此需要占用服务器的资源,并且需要在分布式系统中进行Session共享和Session失效管理(工程量大)。

        Token是无状态的,不需要在服务器端保存用户的登录信息,因此具有良好的可扩展性,并且可以很方便地实现分布式系统中的认证和授权。用解析token的计算时间换取session的存储空间,从而减轻服务器压力,减少频繁查询数据库

        Session的安全性比较高,因为Session的内容保存在服务器端,客户端无法直接修改Session的内容

        Token的安全性相对较低,因为Token的内容保存在客户端,客户端可以通过一些手段来篡改Token的内容。

Session和Token的应用场景:

        一般来说,使用 session 可能更适合传统的 Web 应用,因为它通常需要用户在浏览器中持续地与应用交互,而且涉及到敏感数据的处理。例如,在电子商务网站中,用户需要登录才能访问个人购物车和订单等敏感信息,此时可以使用 session 来验证用户身份,并在服务器端存储相关的用户信息和状态。

        而在 API (应用程序编程接口)设计和单页面应用中,使用 token 可能更加常见。由于 API 和单页面应用的特性,客户端可以直接与 API 或后端服务通信,而不需要经过浏览器的中间层。此时,使用 token 可以避免一些 session 的问题,如跨域和服务器负载均衡等。同时,token 也更容易在不同服务之间进行传递和共享,比如使用 OAuth2 等协议来实现单点登录和授权等功能。文章来源地址https://www.toymoban.com/news/detail-437255.html

到了这里,关于Web应用程序的身份验证:Session认证、Token认证的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Node.js】身份认证,Cookie和Session的认证机制,express中使用session认证和JWT认证

    Web开发模式 基于服务器渲染的传统web开发模式 服务端渲染的概念,服务器发送给客户端的HTNL页面,是在服务器通过字符串的拼接,动态生成的,因此,客户端不需要Ajax这样的技术额外请求页面的数据 优点: 前端耗时少,有利于seo(就是爬虫更容易爬取获得信息,更有利于

    2023年04月11日
    浏览(35)
  • 解释SSL/TLS握手过程&如何设计一个安全的Web应用身份验证机制

    一、请解释SSL/TLS握手过程 SSL/TLS握手过程是实现安全通信的关键步骤,它确保了通信双方能够建立一个加密且可信赖的连接。以下是SSL/TLS握手过程的主要步骤: ClientHello :客户端向服务器发送一个起始握手消息,这个消息包含支持的SSL/TLS版本号、加密套件候选列表以及一个

    2024年04月10日
    浏览(31)
  • Flutter中的Web应用程序开发:构建现代Web应用程序

    作者:禅与计算机程序设计艺术 作为人工智能专家,程序员和软件架构师,CTO,我今天将为大家分享有关 Flutter 中 Web 应用程序开发的见解。在这篇文章中,我们将深入探讨 Flutter Web 应用程序的开发过程、技术原理以及最佳实践。 引言 随着移动设备的普及,Web 应用程序在全

    2024年02月12日
    浏览(62)
  • 解决JAVA“无法验证证书。将不执行该应用程序。”提示

    笔者的一台电脑安装了Java 8 update 361。 需要使用UBNT网桥上的AirView应用(JAVA),但运行时提示: 应用程序出于安全原因被阻止 无法验证证书。 将不执行该应用程序。 名称:AirView 发行者:Ubiquiti Inc. 位置:http://172.16.x.x:80 笔者先前已经在控制面板——Java——安全——“例外

    2024年02月05日
    浏览(34)
  • 使用MediatR和FluentValidation实现CQRS应用程序的数据验证

    本文将重点介绍如何通过MediatR的管道功能将FluentValidation集成到项目中实现验证功能。 CQRS(Command Query Responsibility Segregation)也叫命令查询职责分离,是近年来非常流行的应用程序架构模式。CQRS 背后的理念是在逻辑上将应用程序的流程分成两个独立的流程,即命令或查询。

    2024年02月13日
    浏览(26)
  • 深入理解 Session、Cookie 和 Token:网络安全和身份验证的重要概念

    在当今数字化的世界中,网络安全和身份验证是至关重要的议题。为了实现这些目标,我们常常使用诸如 Session、Cookie 和 Token 等概念。这些概念在 Web 开发、网络通信和安全领域发挥着重要作用。在本文中,我们将深入探讨这些概念的定义、作用以及它们在实际应用中的用途

    2024年03月22日
    浏览(29)
  • Microsoft Office无法验证此应用程序的许可证怎么解决

    启动 Microsoft Office 应用程序(如 Outlook、Word、Excel 或 PowerPoint)时,您可能会收到以下错误消息: 1.选择开始,输入 regedit ,打开注册表 2.导航到 3.右键属性,选择 权限 ,添加 everyone ​ 对everyone用户添加所有权限 重新打开offices就会发现没有提示,问题就解决了。

    2024年02月11日
    浏览(215)
  • Web应用程序安全

    Web应用程序是现代互联网应用的重要组成部分,但是由于其广泛性和复杂性,常常存在各种安全漏洞和风险,如跨站脚本攻击、SQL注入攻击、信息泄露等。为了保障Web应用程序的安全性,需要进行安全性评估,以发现和修复可能存在的安全漏洞和风险。本文将介绍Web应用程序

    2024年02月21日
    浏览(42)
  • 多因素认证与身份验证:分析不同类型的多因素认证方法,介绍如何在访问控制中使用身份验证以增强安全性

    随着数字化时代的到来,信息安全问题变得愈发重要。在网络世界中,用户的身份往往是保护敏感数据和系统免受未经授权访问的第一道防线。单一的密码已经不再足够,多因素认证(MFA)应运而生,成为提升身份验证安全性的重要工具之一。本文将深入探讨不同类型的多因

    2024年02月10日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包