SpringBoot+Vue+Redis实现单点登录(一处登录另一处退出登录)

yizhihongxing

下面是 "SpringBoot+Vue+Redis实现单点登录(一处登录另一处退出登录)" 的完整攻略。

一、前置知识

在讲解实现单点登录的过程中,我们需要掌握以下技术:

  • SpringBoot:后端框架,用来提供 RESTful API 服务;
  • Vue:前端框架,用来构建单页应用;
  • Redis:一个内存数据库,用来保存用户会话信息。

如果对这些技术还不太了解,可以先学习相关的基础知识,再来实践本文的内容。

二、实现思路

单点登录(Single Sign-On)是一种让用户只要登录一次就可以在多个应用中享受无需重复登录的服务。本文实现的单点登录方案,基于 Token 的方式实现,如果用户在一处登录,则可以在其他处直接使用该 Token,而不需要再次输入用户名和密码。当用户在其中一处退出登录时,其他已登录的站点也会失效。

实现该方案的关键点在于 Token 的生成和获取,以及 Token 的存储和验证。下面我们将针对这些点逐一进行讲解。

三、Token 的生成和获取

我们采用 JWT(JSON Web Token)颁发 Token,具体实现过程:

  • 用户在登录成功后,后端服务器使用 JWT 生成 Token,并返回给前端;
  • 前端将 Token 保存在 localStorage 中;
  • 前端携带 Token 向后端请求 API。

当用户在其他页面打开站点时,可以通过读取 localStorage 中保存的 Token,自动向后端请求 API,实现直接登录。

四、Token 的存储和验证

Token 的存储我们使用 Redis,将 Token 以键值对的形式存储在 Redis 中,Key 为 Token 的值,Value 为对应的 user_id。

Token 的验证我们可以利用 SpringBoot 的拦截器,在请求进入后台服务之后,使用 Redis 查询该 Token 对应的 user_id 是否存在,如果存在,则允许请求,如果不存在,则返回未登录状态。

五、示例说明

下面我们来看两个示例,分别说明 Token 的生成和存储,以及 Token 的验证。

1. Token 的生成和存储

后端代码

  1. 引入 JWT 库和 Redis 库。
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 登录生成 Token。
@PostMapping("/login")
public ResponseEntity login(@RequestBody User user) {
    // 校验用户名和密码,生成token
    String token = Jwts.builder()
        .setSubject(user.getUserId())
        .setExpiration(new Date(System.currentTimeMillis() + refreshTokenExpTime))
        .signWith(SignatureAlgorithm.HS512, secret)
        .compact();
    // 存储到redis中
    redisTemplate.opsForValue().set(token, user.getUserId(), refreshTokenExpTime, TimeUnit.MILLISECONDS);

    return ResponseEntity.ok(new Auth(token, refreshTokenExpTime));
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Auth {
    private String token;
    private Long expireTime;
}

前端代码

  1. 登录成功后存储 Token。
export function login(username, password) {
    return request({
        url: '/login',
        method: 'post',
        data: {
            username,
            password
        }
    }).then(response => {
        const {token, expireTime} = response.data;

        localStorage.setItem('token', token);
        localStorage.setItem('expireTime', expireTime);

        return Promise.resolve(response.data);
    });
}

2. Token 的验证

后端代码

  1. 配置 JwtTokenInterceptor 拦截器。
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
    @Autowired
    private JwtTokenInterceptor jwtTokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtTokenInterceptor)
                .excludePathPatterns("/login", "/error", "/static/**");
    }
}
  1. 编写 JwtTokenInterceptor 拦截器验证 Token 有效性。
public class JwtTokenInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("Authorization");

        if (token == null) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }

        // 从redis缓存中查找该key
        String userId = redisTemplate.opsForValue().get(token);

        if (userId == null) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }

        // 将该user_id和token放入threadLocal中,方便后续使用
        UserInfoHolder.setUserId(userId);
        UserInfoHolder.setToken(token);

        return true;
    }
}

前端代码

对于前端来说,我们只需要在请求头中加上 Token 即可。

import axios from 'axios';
import router from '../router';

const service = axios.create({
    baseURL: process.env.VUE_APP_BASE_API,
    timeout: 5000
});

service.interceptors.request.use(
    config => {
        if (localStorage.getItem('token')) {
            // 如果 Token 存在,则在请求头中加入
            config.headers.Authorization = localStorage.getItem('token');
        }

        return config;
    },
    error => {
        return Promise.reject(error);
    }
);

service.interceptors.response.use(
    response => {
        return response;
    },
    error => {
        // 如果请求返回的状态码为 401,表示未经授权,则跳转到登录页
        if (error.response.status === 401) {
            router.push('/login');
        }

        return Promise.reject(error)
    }
);

export default service;

以上就是实现单点登录方案的完整攻略,通过 Token 的存储和验证,我们可以在多个应用中实现单点登录的功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot+Vue+Redis实现单点登录(一处登录另一处退出登录) - Python技术站

(0)
上一篇 2023年6月9日
下一篇 2023年6月9日

相关文章

  • HTML中img标签只显示图片中心位置的方法(三种方法)

    下面我将详细讲解三种方法让HTML中的img标签只显示图片中心位置。 方法一:使用background-image 通过将图片作为 background-image 设置在 div 或者其他块元素上,然后设置 background-position 属性为 center,即可实现只显示图片中心位置。 示例代码: <div class="ima…

    css 2023年6月9日
    00
  • 平面设计

    平面设计 平面设计是指在各种平面上进行视觉传达的设计过程。它是基于一系列原则和元素,通过艺术和技术的手段在平面上组织和安排文字、图形、色彩等,从而达到传达信息、传达情感和美学审美的目的。平面设计在广告、出版、包装、标志、展览等领域得到广泛应用。 设计原则 1. 对齐(Alignment) 对齐指的是在设计中将元素放在同一个边界中形成一种视觉联系。通过对齐,可…

    css 2023年6月10日
    00
  • JavaScript实现图片放大镜效果

    下面我将为您详细讲解如何用JavaScript实现图片放大镜效果。 1. 需求分析 首先,我们需要分析一下需要实现的效果和要实现的功能。放大镜效果通常是这样的:当鼠标悬浮在图片上时,图片中心出现一个放大的镜头,显示鼠标所在位置周围的图像细节。因此,我们需要实现以下功能: 鼠标在图片上移动时,更新放大镜镜头的位置和内容; 根据鼠标位置,在放大镜镜头周围显示放大…

    css 2023年6月10日
    00
  • CSS(div)盒子模型详解

    CSS盒子模型是指一个HTML元素所占用的空间,包括元素内容、内边距、边框和外边距四个部分。这个模型可以用来设置元素在页面中的布局和样式。 在CSS盒子模型中,每一个元素都被看作一个矩形的盒子,其中包含了以下部分: 内容(content):盒子中的内容部分,是我们在HTML中写的文本或图像等。 内边距(padding):内容与边框之间的距离,用来控制元素内容…

    Web开发基础 2023年3月20日
    00
  • 一篇文章带你学习CSS3图片边框

    一篇文章带你学习CSS3图片边框 CSS3为图片边框的设计提供了更加丰富、多样化的方式,可以让我们在网站设计中展现出真正的创意和个性。本文将带领大家学习CSS3图片边框的设计方法,供广大网站设计者参考。 基本语法 CSS3中定义边框的语法如下: selector { border: border-width border-style border-color…

    css 2023年6月10日
    00
  • 浅谈HTML5 & CSS3的新交互特性

    浅谈HTML5 & CSS3的新交互特性 HTML5 & CSS3 是现代Web前端开发的基石。不论是多媒体内容的展示还是用户交互体验的设计,都离不开HTML5和CSS3的特性支持。在此,将介绍一些HTML5 & CSS3的新交互特性及应用。 1. 新的表单类型 HTML5引入了许多新的表单类型,能够更加方便地使用特定格式的数据。 示…

    css 2023年6月10日
    00
  • 常用CSS集合

    常用CSS集合 介绍 在web开发中,CSS是一种用于描述HTML文档样式表现的语言,通过为HTML元素添加样式来控制其外观、布局和交互效果。本文旨在介绍常用的CSS样式,以及如何使用它们来构建美观而功能丰富的网页。 常用样式 文本样式 字体样式 CSS中通过font系列样式来控制字体大小、颜色、样式等。例如: /* 设置字体大小为16像素,字体颜色为红色,…

    css 2023年6月9日
    00
  • 使用css实现全兼容浏览器的三角形

    要使用CSS实现全兼容浏览器的三角形,通常有两种方法。 方法一:使用border实现 使用border属性,可以非常简单地实现三角形效果。假设我们要画一个向右的三角形,可以使用以下代码: .triangle { width: 0; height: 0; border-top: 50px solid transparent; border-bottom: 50…

    css 2023年6月9日
    00
合作推广
合作推广
分享本页
返回顶部