express 里面前后端身份验证 JWT 认证总结

文章讨论了Session认证的跨域限制和JWT(JSONWebToken)作为跨域身份验证的替代方案。它详细介绍了JWT的工作原理、组成部分以及在实际项目中的使用方法,包括在Express框架中的集成和配置。
摘要由CSDN通过智能技术生成

session 认证的缺点

Session 认证机制需要配合 Cookie 才能实现。由于 Cookie 默认不支持跨域访问,所以,当涉及到前端跨域请求后端接口的时候,需要做很多额外的配置,才能实现跨域 Session 认证。
注意:
● 当前端请求后端接口不存在跨域问题的时候,推荐使用 Session 身份认证机制。
● 当前端需要跨域请求后端接口的时候,不推荐使用 Session 身份认证机制,推荐使用 JT 认证机制。

JWT 是什么

JWT(英文全称:JSON Web Token)是目前最流行的跨域认证解决方案。

JWT 认证的工作原理

在这里插入图片描述

总结:用户信息通过 token 字符串的形式,保存在客户端浏览器中,在需要验证身份的接口中,服务端对请求中的头信息进行分析,还原 token 信息来进行身份认证

JWT 的组成部分

由三部分组成,分别是 Header(头部),Payload(有效载荷),Signature(签名),之间用.分割
其中:

  • Payload 部分才是真正的用户信息,"它是用户信息经过加密之后生成的字符串。
  • Header 和 Signature 是安全性相关的部分,只是为了保证 Token 的安全性

JWT 使用方式

客户端收到服务器返回的 JT 之后,通常会将它储存在 localStorage 或 sessionStorage 中。此后,客户端每次与服务器通信,都要带上这个 JWT 的字符串,从而进行身份认证。推荐的做法是把 JWT 放在 HTTP 请求头的 Authorization 字段中,格式如下:

Authrizatuion:Bearer <token>

相关依赖

npm i jsonwebtoken express-jwt

jsonwebtoken 用于生成JWT 字符串
express-jwt 用于将 JWT 字符串解析还原成 JSON 对象

"dependencies": {
    "body-parser": "^1.20.2",
    "cors": "^2.8.5",
    "ejs": "^3.1.9",
    "express": "^4.19.2",
    "express-jwt": "^8.4.1",
    "jsonwebtoken": "^9.0.2",
    "mysql": "^2.18.1"
}

实战代码

入口文件app.js

const express = require("express");
const userRouter = require("./router/user");
const bookRouter = require("./router/book");
const bodyParser = require("body-parser");
const path = require("path");
const cors = require("cors");
const app = express();
const { expressjwt } = require("express-jwt");
const jwtConfig = require("./config/index");

app.use(express.static("public"));
//ejs模版的必须配置
// app.set("view engine", "ejs");
// app.set("views", path.join(__dirname, "views"));
//解析请求体参数
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
//jwt中间件
//安装的express-jwt模块会默认为最新版本,更新后的jwt需要在配置中加入algorithms属性,即设置jwt的算法。一般HS256为配置algorithms的默认值。
app.use(
  expressjwt({ secret: jwtConfig.jwtSecret, algorithms: ["HS256"] }).unless({
    path: [/^\/api\//],
  })
);

//跨域资源共享
app.use(cors());
app.use("/api", userRouter);
app.use("/book", bookRouter);

//错误级别的中间件
app.use((err, req, res, next) => {
  console.log("🚀 ~ app.use ~ err:", err);
  //token解析失败
  if (err.name === "UnauthorizedError") {
    return res.send({
      status: 401,
      message: "无效的token",
    });
  }
  res.send({
    status: 500,
    message: "服务端错误",
  });
});

app.listen(4444, () => {
  console.log("app is running on port 4444");
});

注意:

  • 最新版本的express-jwt这里需要结构 const { expressjwt } = require("express-jwt");
  • 配置项新增的参数algorithms:默认HS256即可,意思是除了以/api/开始的接口外,其余全部需要携带token发送请求
app.use(
  expressjwt({ secret: jwtConfig.jwtSecret, algorithms: ["HS256"] }).unless({
    path: [/^\/api\//],
  })
);

秘钥

const jwtSecret = "gaofeng.8866";
module.exports = {
  jwtSecret,
};

登录模块

const express = require("express");
const router = express.Router();
const jwt = require("jsonwebtoken");

const jwtConfig = require("../config/index");

router.post("/login", (req, res) => {
  const { username, password } = req.body;
  if (username != "admin" && password != "123456") {
    return res.send({
      status: 1,
      msg: "登录失败",
    });
  }
  //登录成功之后,生成jwt字符串,并通过token的形式返回给客户端
  //参数:用户的信息对象,加密的秘钥,配置的对象(当前token的有效期 30s | 2h)
  const token = jwt.sign({ username: username }, jwtConfig.jwtSecret, {
    expiresIn: "30s",
  });
  res.send({
    status: 0,
    msg: "登录成功",
    token,
  });
});

注意:

  • 登录成功之后,生成jwt字符串,并通过token的形式返回给客户端
  • 参数:用户的信息对象,加密的秘钥,配置的对象(当前token的有效期 30s | 2h)

测试验证

  • 不携带及过期token,都会被全局的错误中间件拦截,并返回定制的错误消息

在这里插入图片描述

  • 登录
    在这里插入图片描述
    这样就返回了token字符串

  • 再次发起预约接口

在这里插入图片描述
这样我们就实现了jwt身份鉴权验证

我们在其他接口中解析客户端的token信息的时候,最新版的express-jwt有变化,需要使用req.auth来获取客户端的token,与较早版本的获取方式有差异,req.user,这里需要注意!!!
在这里插入图片描述
到这里,关于jwt鉴权我们就算是完成了!!!_

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JWT(JSON Web Token)是一种基于 JSON 的安全令牌,它可以在客户端和服务器之间安全传输信息。在前后端分离的项目中,使用 JWT 进行用户认证可以方便地处理用户登录和权限控制。 以下是使用 Spring Boot 和 JWT 实现前后端分离的用户认证示例: 1. 添加依赖 在 pom.xml 中添加以下依赖: ```xml <!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> ``` 2. 创建 JWT 工具类 创建一个 JWT 工具类,用于生成和验证 JWT。以下是一个简单的实现: ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; import java.util.Map; @Component public class JwtUtils { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private Long expiration; public String generateToken(String username) { Map<String, Object> claims = new HashMap<>(); claims.put("sub", username); claims.put("iat", new Date()); return Jwts.builder() .setClaims(claims) .setExpiration(new Date(System.currentTimeMillis() + expiration)) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } public String getUsernameFromToken(String token) { try { Claims claims = Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } catch (Exception e) { return null; } } public boolean validateToken(String token, String username) { String tokenUsername = getUsernameFromToken(token); return tokenUsername != null && tokenUsername.equals(username); } } ``` 3. 创建登录接口 创建一个登录接口,用于验证用户的用户名和密码,并返回 JWT: ```java @PostMapping("/login") public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())); SecurityContextHolder.getContext().setAuthentication(authentication); String jwt = jwtUtils.generateToken(authentication.getName()); return ResponseEntity.ok(new JwtResponse(jwt)); } ``` 4. 创建受保护的接口 创建一个受保护的接口,需要用户在请求头中传递 JWT。在该接口中,首先验证 JWT 是否有效,然后根据用户角色返回相应的数据: ```java @GetMapping("/data") @PreAuthorize("hasAnyRole('USER', 'ADMIN')") public ResponseEntity<?> getData() { String username = SecurityContextHolder.getContext().getAuthentication().getName(); if (jwtUtils.validateToken(jwt, username)) { // 返回数据 } else { throw new BadCredentialsException("Invalid JWT"); } } ``` 5. 配置 JWT 相关属性 在 application.properties 中配置 JWT 相关属性: ``` jwt.secret=mySecret jwt.expiration=86400000 # 1 day in milliseconds ``` 以上就是使用 Spring Boot 和 JWT 实现前后端分离的用户认证的示例。需要注意的是,JWT 本身并没有提供加密功能,因此需要使用一个密钥来保证 JWT 的安全性。在示例中,密钥存储在配置文件中,实际生产环境中应该使用更加安全的方式来存储密钥。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值