亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

JWT單點登錄學習入門指南

標簽:
安全 運維 API
概述

JWT单点登录学习入门介绍了一种基于JWT实现跨应用安全身份验证的方法,适用于无状态的服务。文章详细讲解了JWT的基础概念、单点登录的重要性以及如何使用JWT实现单点登录的步骤。通过示例代码,读者可以轻松上手实践JWT单点登录的开发。JWT单点登录不仅提升了用户体验,还有效降低了系统的维护成本。

JWT单点登录学习入门指南
JWT基础概念介绍

什么是JWT

JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式用于通信双方之间安全地传输信息。JWT可以被用于身份验证和信息交换。它由三部分组成:头部(Header)、载荷(Payload)、签名(Signature)。

JWT的构成

JWT由三部分组成,每部分由一个点(.)分隔,分别是头部、载荷和签名:

  1. 头部:包含令牌的类型(即JWT)和所使用的签名算法信息(例如HMAC SHA256或RSA)。示例头部:

    {
     "typ": "JWT",
     "alg": "HS256"
    }
  2. 载荷:载荷可以存放声明(声明是键值对形式的简单数据),这些声明是JWT的主体部分,通常用于存放用户的标识、角色、权限等信息。示例载荷:

    {
     "sub": "1234567890",
     "name": "John Doe",
     "admin": true,
     "exp": 1516239022
    }
  3. 签名:签名用于保证JWT的完整性和防篡改。它通过头部定义的算法,使用头部的密钥和载荷数据计算生成。

JWT的优势

  1. 无状态:服务器无需保存JWT的状态信息,减轻了服务器的负担。
  2. 安全性:生成的JWT是不可篡改的,客户端可以在每次请求时携带JWT,服务器可以验证其有效性。
  3. 可扩展性:可以在载荷中添加更多的自定义信息,而不会影响到原来的JWT结构。
  4. 易于传输:JWT是一个简单的字符串,可以通过HTTP请求头或URL参数进行传输。

JWT的劣势

  1. 大小限制:JWT的大小有限制,超过一定长度可能会影响性能。
  2. 安全性依赖于密钥:JWT的安全性完全依赖于密钥的安全性,一旦密钥泄露,所有使用该密钥生成的JWT都会失效。
单点登录的基本原理

单点登录定义

单点登录(Single Sign-On,简称SSO)是一种身份验证机制,允许用户使用一组凭证登录一个系统后,无需再次输入凭证即可访问其他系统。这种机制能够提升用户体验,减少凭证管理的复杂度。

单点登录的重要性

  1. 用户体验:用户无需记住多个账户密码,简化了登录过程。
  2. 安全性:通过集中管理用户凭证,减少安全漏洞的风险。
  3. 维护成本:集中管理用户身份,减少了维护多个系统的开销。

常见单点登录实现方式

  1. Cookie:通过共享Cookie实现,但这种方式依赖于浏览器Cookie,不适用于无状态服务。
  2. OAuth:OAuth是一种开放授权协议,可以实现跨应用的单点登录,需要中间件支持。
  3. JWT:通过JWT实现单点登录,适用于无状态服务,易于跨域使用。
使用JWT实现单点登录的步骤

准备工作

  1. 环境准备:确保已安装Node.js和npm。
  2. 工具选择:选择适合的开发工具,例如VSCode。
  3. 库安装:使用npm安装JWT相关库。
    npm install jsonwebtoken express body-parser cors

创建JWT

创建JWT需要生成头部、载荷和签名。头部和载荷是JSON对象,签名是通过指定的算法生成的。

const jwt = require('jsonwebtoken');

// 创建头部
const header = {
  alg: 'HS256',
  typ: 'JWT'
};

// 创建载荷
const payload = {
  user: 'john_doe',
  role: 'admin',
  exp: Math.floor(Date.now() / 1000) + (60 * 60)  // 有效时间为1小时
};

// 生成签名
const secret = 'supersecretkey';

const token = jwt.sign(payload, secret, { algorithm: 'HS256' });
console.log(token);

验证JWT

验证JWT需要检查签名和载荷的有效性。

const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiam9obiRkb2UiLCJyb2xlIjoiYWRtaW4iLCJleHAiOiIyMDE5LTA3LTIwVDA5OjEwOjQ4LjI1OVoiLCJzdWIiOiIxMjM0NTY3ODkwIn0.0XwP4E0ZiR8w4lJW4BQW301ZcF482U492w0H42w94';

try {
  const decoded = jwt.verify(token, secret);
  console.log(decoded);
} catch (err) {
  console.error(err);
}

实现用户身份验证

const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');

const app = express();
const secret = 'supersecretkey';
const port = 3000;

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// 登录接口
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  // 这里应该有用户验证逻辑
  const user = { username: "john_doe", password: "password123" };

  if (username === user.username && password === user.password) {
    const token = jwt.sign({ username: user.username }, secret, { expiresIn: '1h' });
    res.json({ token });
  } else {
    res.status(401).json({ message: 'Invalid credentials' });
  }
});

// 需要身份验证的接口
app.get('/protected', (req, res) => {
  const token = req.headers.authorization;
  if (token) {
    jwt.verify(token, secret, (err, decoded) => {
      if (err) {
        return res.status(403).json({ message: 'Invalid token' });
      }
      res.json({ message: 'Welcome authenticated user', user: decoded });
    });
  } else {
    res.status(403).json({ message: 'No token provided' });
  }
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

跨域请求中的JWT使用

const cors = require('cors');

app.use(cors({
  credentials: true,
  origin: ['http://localhost:3001'] // 允许跨域请求的前端地址
}));

// 在前端获取token后添加到请求头部
fetch('http://localhost:3000/protected', {
  method: 'GET',
  headers: { 'Authorization': `Bearer ${token}` },
  credentials: 'include'
}).then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));
实际案例演示

选择编程语言和框架

选择Node.js作为服务端语言,使用Express框架。Node.js和Express是开发无状态服务的理想选择,因为它们轻量、易于扩展,且能够很好地支持异步操作。

搭建开发环境

  1. 创建新的Node.js项目
    mkdir jwt-sso
    cd jwt-sso
    npm init -y
  2. 安装必要的依赖
    npm install express jsonwebtoken body-parser cors

编写代码实现JWT单点登录

  1. 创建登录接口
const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const cors = require('cors');

const app = express();
const secret = 'supersecretkey';
const port = 3000;

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors({ credentials: true, origin: ['http://localhost:3001'] }));

const users = [
  { username: 'john', password: '12345' },
  { username: 'jane', password: '56789' }
];

// 登录接口
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = users.find(user => user.username === username && user.password === password);

  if (user) {
    const token = jwt.sign({ username: user.username }, secret, { expiresIn: '1h' });
    res.json({ token });
  } else {
    res.status(401).json({ message: 'Invalid credentials' });
  }
});

// 需要身份验证的接口
app.get('/protected', (req, res) => {
  const token = req.headers.authorization?.split(' ')[1];

  if (token) {
    jwt.verify(token, secret, (err, decoded) => {
      if (err) {
        return res.status(403).json({ message: 'Invalid token' });
      }
      res.json({ message: 'Welcome authenticated user', user: decoded });
    });
  } else {
    res.status(403).json({ message: 'No token provided' });
  }
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
  1. 前端代码
<!DOCTYPE html>
<html>
<head>
  <title>JWT SSO Demo</title>
  <script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
  <h1>Login</h1>
  <form id="loginForm">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username"><br>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password"><br>
    <button type="submit">Login</button>
  </form>
  <script>
    const loginForm = document.getElementById('loginForm');
    loginForm.addEventListener('submit', (e) => {
      e.preventDefault();
      const username = loginForm.elements['username'].value;
      const password = loginForm.elements['password'].value;

      axios.post('http://localhost:3000/login', { username, password })
        .then(response => {
          localStorage.setItem('token', response.data.token);
          alert('Login successful');
        })
        .catch(error => {
          console.error(error);
          alert('Login failed');
        });
    });

    const protectedButton = document.getElementById('protectedButton');
    protectedButton.addEventListener('click', () => {
      const token = localStorage.getItem('token');
      axios.get('http://localhost:3000/protected', {
        headers: { 'Authorization': `Bearer ${token}` }
      })
        .then(response => {
          console.log(response.data);
          alert('Protected resource accessed successfully');
        })
        .catch(error => {
          console.error(error);
          alert('Failed to access protected resource');
        });
    });
  </script>
  <button id="protectedButton">Access Protected Resource</button>
</body>
</html>
常见问题及解决方法

JWT时间戳问题解决

  1. 过期时间设置:在生成JWT时设置过期时间(例如1小时)。
  2. 自动刷新:前端可以存储过期时间,当请求时检查时间戳是否过期,如果过期则重新登录或刷新JWT。

JWT安全性提升策略

  1. 密钥安全:密钥应妥善保管,不应泄露。
  2. 签名算法:使用更安全的签名算法,如RS256。
  3. 传输安全:确保JWT通过HTTPS传输,防止中间人攻击。

身份验证错误处理

  1. 错误提示:当用户登录失败时显示具体的错误信息。
  2. 前端处理:前端在接收到错误响应时提示用户,而不是直接显示错误信息。
  3. 日志记录:服务端记录详细的错误日志,便于排查问题。
总结与后续学习方向

JWT单点登录总结

JWT单点登录是实现跨应用身份验证的一种有效手段。通过JWT,开发者可以轻松地在无状态的服务中实现安全的身份验证。同时,JWT的无状态性、安全性以及易于传输的特点使其成为现代应用程序的首选。

推荐进一步学习的资源

  • 慕课网:提供了丰富的在线课程,涵盖从基础到高级的JWT单点登录教程。
  • 官方文档:JWT官方文档提供了详细的用法和最佳实践。
  • 在线教程:Web开发社区和论坛,如Stack Overflow,提供了大量的实际案例和问题解答。
點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消