Spring Boot 安全登录系统:前后端分离实现

发布于:2025-07-14 ⋅ 阅读:(15) ⋅ 点赞:(0)

关键词:Spring Boot、安全登录、JWT、Shiro / Spring Security、前后端分离、Vue、MySQL


详细代码请参考这篇文章:完整 Spring Boot + Vue 登录

✅ 摘要

在现代 Web 应用中,用户登录与权限控制是系统安全性的基础环节。本文将手把手带你实现一个基于 Spring Boot + JWT + Shiro/Spring Security 的安全登录系统,并配合前端 Vue 实现前后端分离架构。

内容涵盖:

  • 后端接口设计(登录、注册、权限验证)
  • 使用 JWT 生成 Token
  • 使用 Shiro 或 Spring Security 实现权限管理
  • 前端 Vue 登录页面与 Token 存储示例
  • 跨域配置、拦截器校验 Token
  • 完整数据库表结构(MySQL)

每部分都配有 完整的 Java 示例代码、Vue 页面代码和数据库脚本


📌 一、项目结构说明

springboot-login/
├── backend/            # Spring Boot 后端模块
│   ├── src/main/java     # Java源码
│   └── application.yml   # 配置文件
├── frontend/           # Vue 前端模块(可选)
│   ├── src/views         # 登录页组件
│   └── main.js           # Axios 请求封装
└── README.md

📌 二、数据库设计(MySQL)

用户表:sys_user

CREATE TABLE sys_user (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(100) NOT NULL,
    nickname VARCHAR(50),
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

📌 三、后端实现(Spring Boot + JWT)

1. 添加依赖(pom.xml)

<!-- Spring Boot Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- JWT 工具 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

<!-- MyBatis Plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3</version>
</dependency>

<!-- Shiro 权限框架(可替换为 Spring Security) -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.9.1</version>
</dependency>

2. JWT 工具类(JwtUtils.java)

import io.jsonwebtoken.*;
import java.util.Date;

public class JwtUtils {
    private static final String SECRET = "your-secret-key";
    private static final long EXPIRATION = 86400000; // 24小时

    public static String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
            .signWith(SignatureAlgorithm.HS512, SECRET)
            .compact();
    }

    public static String parseToken(String token) {
        return Jwts.parser()
            .setSigningKey(SECRET)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }
}

3. 登录接口(UserController.java)

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest request) {
        SysUser user = userService.findByUsername(request.getUsername());
        if (user == null || !user.getPassword().equals(request.getPassword())) {
            throw new RuntimeException("用户名或密码错误");
        }

        String token = JwtUtils.generateToken(user.getUsername());

        return ResponseEntity.ok()
            .header("Authorization", "Bearer " + token)
            .build();
    }
}

4. 自定义拦截器(JwtInterceptor.java)

@Component
public class JwtInterceptor implements HandlerInterceptor {

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

        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            String username = JwtUtils.parseToken(token);

            // 可以结合 Shiro 或 Spring Security 设置认证信息
            UsernamePasswordToken shiroToken = new UsernamePasswordToken(username, "");
            SecurityUtils.getSubject().login(shiroToken);
        }

        return true;
    }
}

5. 注册拦截器(WebConfig.java)

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private JwtInterceptor jwtInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/api/auth/login");
    }
}

📌 四、前端实现(Vue + Axios)

1. 登录页面组件(Login.vue)

<template>
  <div>
    <input v-model="username" placeholder="用户名">
    <input v-model="password" type="password" placeholder="密码">
    <button @click="login">登录</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      username: '',
      password: ''
    };
  },
  methods: {
    async login() {
      const res = await this.$axios.post('/api/auth/login', {
        username: this.username,
        password: this.password
      });
      const token = res.headers.authorization;
      localStorage.setItem('token', token);
      this.$router.push('/');
    }
  }
};
</script>

2. Axios 封装(main.js)

import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'http://localhost:8080',
});

// 请求拦截器添加 Token
apiClient.interceptors.request.use(config => {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers.Authorization = token;
  }
  return config;
});

Vue.prototype.$axios = apiClient;

📌 五、跨域配置(application.yml)

spring:
  mvc:
    async:
      request-timeout: -1
  cors:
    allowed-origins: "*"
    allowed-methods: "*"
    allowed-headers: "*"

✅ 总结

功能 技术栈 说明
登录接口 Spring Boot 接收用户名密码,返回 Token
Token 管理 JWT 生成与解析 Token
权限控制 Shiro / Spring Security 控制访问权限
前端登录 Vue 使用 Axios 发起请求并存储 Token
Token 校验 拦截器 每次请求校验 Token 并设置用户上下文

📚 参考资料


网站公告

今日签到

点亮在社区的每一天
去签到