前言
在spring boot项目开发中,完成接口开发只是基础,接口的安全控制才是提升项目专业度的关键——如果接口没有权限校验,任何人都能随意调用接口、操作数据,会造成严重的安全隐患。本文承接“接口开发完成后无安全控制”的场景,手把手教大家实现用户登录接口、整合jwt完成令牌生成与验证,以及通过拦截器/过滤器实现接口权限校验,完整落地接口安全体系,适配实际项目与毕设需求,快速提升开发专业度。
一、前置准备:环境搭建与核心依赖
本次实战基于spring boot + mybatis-plus + jwt + spring security(简化版),核心依赖如下,无需额外引入过多复杂组件,兼顾轻量与实用。
1.1 maven 核心依赖
<!-- spring boot web 核心依赖 -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<!-- mybatis-plus 核心依赖(操作数据库) -->
<dependency>
<groupid>com.baomidou</groupid>
<artifactid>mybatis-plus-boot-starter</artifactid>
<version>3.5.3.1</version>
</dependency>
<!-- mysql 驱动 -->
<dependency>
<groupid>com.mysql</groupid>
<artifactid>mysql-connector-j</artifactid>
<scope>runtime</scope>
</dependency>
<!-- jwt 核心依赖(生成/验证令牌) -->
<dependency>
<groupid>io.jsonwebtoken</groupid>
<artifactid>jjwt-api</artifactid>
<version>0.11.5</version>
</dependency>
<dependency>
<groupid>io.jsonwebtoken</groupid>
<artifactid>jjwt-impl</artifactid>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupid>io.jsonwebtoken</groupid>
<artifactid>jjwt-jackson</artifactid>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- lombok 简化实体类 -->
<dependency>
<groupid>org.projectlombok</groupid>
<artifactid>lombok</artifactid>
<optional>true</optional>
</dependency>
<!-- spring security 简化版(可选,用于权限注解) -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-security</artifactid>
</dependency>
1.2 核心配置(application.yml)
配置数据库连接、jwt核心参数(密钥、过期时间)、mybatis-plus相关配置,集中管理,便于后续修改:
spring:
# 数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.driver
url: jdbc:mysql://localhost:3306/springboot_jwt?useunicode=true&characterencoding=utf-8&servertimezone=gmt%2b8
username: root
password: 123456
# spring security 配置(关闭默认登录页,简化配置)
security:
basic:
enabled: false
user:
name: admin
password: admin
# mybatis-plus 配置
mybatis-plus:
mapper-locations: classpath:mybatis/mapper/**/*.xml
type-aliases-package: com.example.demo.entity
configuration:
map-underscore-to-camel-case: true # 驼峰命名映射
log-impl: org.apache.ibatis.logging.stdout.stdoutimpl # 打印sql日志(便于调试)
# jwt 自定义配置(自己定义,后续代码中读取)
jwt:
secret: springboot-jwt-2026-security-key # 密钥(生产环境需更换为复杂密钥,避免泄露)
expiration: 86400000 # 令牌过期时间(单位:毫秒),这里设置为24小时
header: authorization # 请求头中携带令牌的字段名,默认authorization
1.3 数据库表设计(用户表)
核心是用户表,存储用户名、密码(加密存储)、角色(用于后续权限区分,简化版用字符串表示),无需复杂设计,适配登录与权限校验核心需求:
create table `sys_user` ( `id` bigint(20) not null auto_increment comment '用户主键', `username` varchar(50) not null comment '用户名(唯一)', `password` varchar(100) not null comment '密码(加密存储)', `role` varchar(20) not null comment '用户角色(如:admin、user)', `status` tinyint(1) default 1 comment '状态(1:正常,0:禁用)', `create_time` datetime default current_timestamp comment '创建时间', primary key (`id`), unique key `uk_username` (`username`) ) engine=innodb default charset=utf8mb4 comment='系统用户表';
说明:密码需加密存储(本文使用bcrypt加密,spring security自带,无需额外引入工具),禁止明文存储,避免安全风险。
二、核心实战一:用户登录接口设计
登录接口是权限控制的入口,核心逻辑:接收前端传入的用户名/密码 → 校验用户名是否存在、密码是否匹配 → 校验通过生成jwt令牌 → 返回令牌给前端;校验失败返回错误信息。
2.1 实体类与dto设计
2.1.1 用户实体类(sysuser)
import com.baomidou.mybatisplus.annotation.*;
import lombok.data;
import java.time.localdatetime;
/**
* 系统用户实体类
*/
@data
@tablename("sys_user")
public class sysuser {
@tableid(type = idtype.auto)
private long id;
// 用户名(唯一)
private string username;
// 加密后的密码
private string password;
// 用户角色(admin:管理员,user:普通用户)
private string role;
// 状态(1:正常,0:禁用)
private integer status;
@tablefield(fill = fieldfill.insert)
private localdatetime createtime;
}
2.1.2 登录请求dto(logindto)
接收前端传入的登录参数,用于参数校验(用户名、密码非空):
import lombok.data;
import javax.validation.constraints.notblank;
/**
* 登录请求dto(接收前端参数)
*/
@data
public class logindto {
// 用户名,非空校验
@notblank(message = "用户名不能为空")
private string username;
// 密码,非空校验
@notblank(message = "密码不能为空")
private string password;
}
2.1.3 登录响应dto(loginvo)
返回给前端的结果,包含jwt令牌、用户名、角色等信息,避免返回敏感数据(如加密后的密码):
import lombok.data;
/**
* 登录响应vo(返回给前端)
*/
@data
public class loginvo {
// jwt令牌
private string token;
// 用户名
private string username;
// 用户角色
private string role;
// 令牌过期时间(单位:毫秒)
private long expiration;
}
2.2 mapper、service层实现(用户校验)
2.2.1 sysusermapper
import com.baomidou.mybatisplus.core.mapper.basemapper;
import com.example.demo.entity.sysuser;
import org.apache.ibatis.annotations.mapper;
import org.apache.ibatis.annotations.param;
/**
* 用户mapper接口
*/
@mapper
public interface sysusermapper extends basemapper<sysuser> {
// 根据用户名查询用户(登录核心查询)
sysuser selectbyusername(@param("username") string username);
}
2.2.2 sysuserservice
核心是用户校验逻辑:查询用户、校验密码、校验用户状态,使用spring security的bcryptpasswordencoder进行密码加密与匹配:
import com.baomidou.mybatisplus.extension.service.impl.serviceimpl;
import com.example.demo.entity.sysuser;
import com.example.demo.mapper.sysusermapper;
import com.example.demo.util.jwtutil;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.security.crypto.bcrypt.bcryptpasswordencoder;
import org.springframework.stereotype.service;
import org.springframework.util.assert;
/**
* 用户service层
*/
@service
public class sysuserservice extends serviceimpl<sysusermapper, sysuser> {
@autowired
private sysusermapper sysusermapper;
// bcrypt密码加密器(spring security自带)
private final bcryptpasswordencoder passwordencoder = new bcryptpasswordencoder();
/**
* 登录校验:根据用户名和密码校验用户
* @param username 用户名
* @param password 明文密码
* @return 校验通过的用户信息
*/
public sysuser logincheck(string username, string password) {
// 1. 根据用户名查询用户
sysuser user = sysusermapper.selectbyusername(username);
assert.notnull(user, "用户名不存在");
// 2. 校验用户状态(是否禁用)
assert.istrue(user.getstatus() == 1, "用户已禁用,请联系管理员");
// 3. 校验密码(明文密码与数据库加密密码匹配)
assert.istrue(passwordencoder.matches(password, user.getpassword()), "密码错误");
// 4. 校验通过,返回用户信息(注意:不要返回密码)
user.setpassword(null);
return user;
}
/**
* 新增用户(用于测试,密码自动加密)
* @param user 用户信息
* @return 新增结果
*/
public boolean adduser(sysuser user) {
// 密码加密后存储
user.setpassword(passwordencoder.encode(user.getpassword()));
return save(user);
}
}
2.3 controller层:登录接口实现
接收前端请求,调用service层校验用户,校验通过后调用jwt工具类生成令牌,返回登录结果:
import com.example.demo.dto.logindto;
import com.example.demo.dto.loginvo;
import com.example.demo.entity.sysuser;
import com.example.demo.service.sysuserservice;
import com.example.demo.util.jwtutil;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.beans.factory.annotation.value;
import org.springframework.validation.annotation.validated;
import org.springframework.web.bind.annotation.postmapping;
import org.springframework.web.bind.annotation.requestbody;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.restcontroller;
import javax.validation.valid;
/**
* 登录控制器
*/
@restcontroller
@requestmapping("/auth")
@validated
public class logincontroller {
@autowired
private sysuserservice sysuserservice;
@autowired
private jwtutil jwtutil;
// 从配置文件读取jwt过期时间
@value("${jwt.expiration}")
private long expiration;
/**
* 用户登录接口
* @param logindto 登录参数(用户名、密码)
* @return 登录结果(jwt令牌等)
*/
@postmapping("/login")
public loginvo login(@valid @requestbody logindto logindto) {
// 1. 登录校验(用户名、密码、用户状态)
sysuser user = sysuserservice.logincheck(logindto.getusername(), logindto.getpassword());
// 2. 生成jwt令牌(传入用户id、用户名、角色)
string token = jwtutil.generatetoken(user.getid(), user.getusername(), user.getrole());
// 3. 组装返回结果
loginvo loginvo = new loginvo();
loginvo.settoken(token);
loginvo.setusername(user.getusername());
loginvo.setrole(user.getrole());
loginvo.setexpiration(expiration);
return loginvo;
}
}
2.4 测试登录接口
先调用adduser方法新增测试用户(如username=admin,password=123456,role=admin),密码会自动加密存储;
2. 用postman调用post接口:http://localhost:8080/auth/login,请求体如下:
{
"username": "admin",
"password": "123456"
}
- 响应结果(成功):返回token、username、role、expiration,前端需存储token,后续请求接口时携带该token。
三、核心实战二:jwt 生成与验证(工具类实现)
jwt(json web token)是一种无状态的令牌机制,核心优势是无需在服务器存储会话信息,仅通过令牌本身即可完成身份验证,适合分布式系统。本文封装jwt工具类,实现令牌生成、验证、解析核心功能。
3.1 jwt工具类(jwtutil)
核心逻辑:读取配置文件中的密钥和过期时间,使用jjwt依赖提供的api生成令牌、验证令牌有效性、解析令牌中的用户信息(用户id、用户名、角色)。
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.value;
import org.springframework.stereotype.component;
import java.util.date;
/**
* jwt工具类:生成令牌、验证令牌、解析令牌
*/
@component
public class jwtutil {
// 从配置文件读取jwt密钥
@value("${jwt.secret}")
private string secret;
// 从配置文件读取令牌过期时间(毫秒)
@value("${jwt.expiration}")
private long expiration;
// 令牌前缀(规范写法,前端请求头携带时需加上)
private static final string token_prefix = "bearer ";
/**
* 生成jwt令牌
* @param userid 用户id
* @param username 用户名
* @param role 用户角色
* @return jwt令牌(不带前缀)
*/
public string generatetoken(long userid, string username, string role) {
// 令牌过期时间 = 当前时间 + 配置的过期时间
date expirationdate = new date(system.currenttimemillis() + expiration);
// 构建jwt令牌
return jwts.builder()
// 载荷:存储用户核心信息(自定义字段)
.claim("userid", userid)
.claim("username", username)
.claim("role", role)
// 主题(可自定义,一般存储用户名)
.setsubject(username)
// 签发时间
.setissuedat(new date())
// 过期时间
.setexpiration(expirationdate)
// 签名算法:hs256,使用配置的密钥
.signwith(signaturealgorithm.hs256, secret)
// 压缩令牌
.compact();
}
/**
* 验证jwt令牌有效性
* @param token 待验证的令牌(可带前缀,也可不带)
* @return true:有效,false:无效
*/
public boolean validatetoken(string token) {
try {
// 去除令牌前缀(如果有)
token = token.replace(token_prefix, "");
// 解析令牌,验证签名和过期时间
jwts.parser().setsigningkey(secret).parseclaimsjws(token);
return true;
} catch (exception e) {
// 捕获所有异常(签名错误、令牌过期、格式错误等)
return false;
}
}
/**
* 解析jwt令牌,获取载荷中的用户信息(通用方法)
* @param token 令牌(可带前缀)
* @return 载荷对象(包含自定义的userid、username、role)
*/
public claims parsetoken(string token) {
token = token.replace(token_prefix, "");
return jwts.parser()
.setsigningkey(secret)
.parseclaimsjws(token)
.getbody();
}
/**
* 从令牌中获取用户名
* @param token 令牌
* @return 用户名
*/
public string getusernamefromtoken(string token) {
claims claims = parsetoken(token);
return claims.get("username", string.class);
}
/**
* 从令牌中获取用户角色
* @param token 令牌
* @return 用户角色
*/
public string getrolefromtoken(string token) {
claims claims = parsetoken(token);
return claims.get("role", string.class);
}
/**
* 从令牌中获取用户id
* @param token 令牌
* @return 用户id
*/
public long getuseridfromtoken(string token) {
claims claims = parsetoken(token);
return claims.get("userid", long.class);
}
}
3.2 jwt核心注意事项
1. 密钥(secret):生产环境必须更换为复杂的随机字符串(如32位随机字符),避免泄露,否则会导致令牌被伪造; 2. 过期时间(expiration):根据业务需求设置,一般为1-24小时,过期后前端需重新登录获取新令牌; 3. 载荷信息:仅存储非敏感核心信息(如用户id、用户名、角色),禁止存储密码、手机号等敏感数据; 4. 令牌前缀:前端请求时,需在请求头authorization中携带令牌,格式为:bearer + 空格 + 令牌(如:bearer eyjhbgcioijiuzi1nij9...)。
四、核心实战三:拦截器 / 过滤器实现接口权限校验
生成jwt令牌后,需要拦截所有需要权限的接口,校验令牌的有效性、用户的权限,实现接口保护。本文分别实现两种方式:拦截器(handlerinterceptor)和过滤器(filter),按需选择,核心逻辑一致。
方式一:拦截器(handlerinterceptor)实现权限校验
拦截器是spring mvc提供的组件,可拦截请求的预处理、后处理,适合与spring生态整合,便于获取spring容器中的bean(如jwtutil),推荐使用。
4.1.1 自定义拦截器(jwtinterceptor)
核心逻辑:拦截请求 → 从请求头获取令牌 → 验证令牌有效性 → 解析用户信息 → 校验用户权限(可选) → 放行;若令牌无效/无令牌,直接返回401未授权。
import com.example.demo.util.jwtutil;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.beans.factory.annotation.value;
import org.springframework.stereotype.component;
import org.springframework.web.servlet.handlerinterceptor;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import java.io.printwriter;
/**
* jwt拦截器:实现接口权限校验
*/
@component
public class jwtinterceptor implements handlerinterceptor {
@autowired
private jwtutil jwtutil;
// 从配置文件读取请求头中令牌的字段名
@value("${jwt.header}")
private string jwtheader;
/**
* 请求预处理(核心方法):在接口执行前拦截,校验令牌
*/
@override
public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception {
// 1. 从请求头中获取令牌
string token = request.getheader(jwtheader);
// 2. 校验令牌是否存在
if (token == null || token.trim().isempty()) {
responseerror(response, "未携带令牌,请先登录");
return false;
}
// 3. 验证令牌有效性
if (!jwtutil.validatetoken(token)) {
responseerror(response, "令牌无效或已过期,请重新登录");
return false;
}
// 4. (可选)权限校验:根据业务需求,校验用户角色是否有权限访问当前接口
// 示例:假设/admin/**接口只有admin角色可访问
string requesturi = request.getrequesturi();
string role = jwtutil.getrolefromtoken(token);
if (requesturi.startswith("/admin/") && !"admin".equals(role)) {
responseerror(response, "权限不足,无法访问");
return false;
}
// 5. 令牌校验通过,放行请求
return true;
}
/**
* 响应错误信息(统一返回json格式)
*/
private void responseerror(httpservletresponse response, string message) throws exception {
response.setcontenttype("application/json;charset=utf-8");
response.setstatus(httpservletresponse.sc_unauthorized); // 401未授权
printwriter out = response.getwriter();
out.write("{\"code\":401,\"message\":\"" + message + "\"}");
out.flush();
out.close();
}
}
4.1.2 注册拦截器(配置拦截规则)
通过webmvcconfigurer配置拦截器,指定拦截哪些接口、放行哪些接口(如登录接口无需拦截):
import com.example.demo.interceptor.jwtinterceptor;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.context.annotation.configuration;
import org.springframework.web.servlet.config.annotation.interceptorregistry;
import org.springframework.web.servlet.config.annotation.webmvcconfigurer;
/**
* spring mvc 配置:注册jwt拦截器
*/
@configuration
public class webmvcconfig implements webmvcconfigurer {
@autowired
private jwtinterceptor jwtinterceptor;
@override
public void addinterceptors(interceptorregistry registry) {
registry.addinterceptor(jwtinterceptor)
// 拦截所有接口
.addpathpatterns("/**")
// 放行接口(无需权限校验)
.excludepathpatterns(
"/auth/login", // 登录接口
"/auth/register", // 注册接口(如果有)
"/swagger-ui/**", // swagger文档(开发环境放行)
"/v3/api-docs/**" // swagger接口(开发环境放行)
);
}
}
方式二:过滤器(filter)实现权限校验
过滤器是servlet提供的组件,作用于请求进入servlet之前,更底层,适合通用的权限校验场景。实现逻辑与拦截器一致,仅代码写法不同。
4.2.1 自定义过滤器(jwtfilter)
import com.example.demo.util.jwtutil;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.beans.factory.annotation.value;
import org.springframework.stereotype.component;
import javax.servlet.*;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import java.io.ioexception;
import java.io.printwriter;
/**
* jwt过滤器:实现接口权限校验
*/
@component
public class jwtfilter implements filter {
@autowired
private jwtutil jwtutil;
@value("${jwt.header}")
private string jwtheader;
@override
public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception {
httpservletrequest request = (httpservletrequest) servletrequest;
httpservletresponse response = (httpservletresponse) servletresponse;
// 1. 获取令牌
string token = request.getheader(jwtheader);
// 2. 校验令牌是否存在
if (token == null || token.trim().isempty()) {
responseerror(response, "未携带令牌,请先登录");
return;
}
// 3. 验证令牌有效性
if (!jwtutil.validatetoken(token)) {
responseerror(response, "令牌无效或已过期,请重新登录");
return;
}
// 4. (可选)权限校验(与拦截器逻辑一致)
string requesturi = request.getrequesturi();
string role = jwtutil.getrolefromtoken(token);
if (requesturi.startswith("/admin/") && !"admin".equals(role)) {
responseerror(response, "权限不足,无法访问");
return;
}
// 5. 放行请求
filterchain.dofilter(request, response);
}
// 响应错误信息(与拦截器一致)
private void responseerror(httpservletresponse response, string message) throws ioexception {
response.setcontenttype("application/json;charset=utf-8");
response.setstatus(httpservletresponse.sc_unauthorized);
printwriter out = response.getwriter();
out.write("{\"code\":401,\"message\":\"" + message + "\"}");
out.flush();
out.close();
}
}
4.2.2 注册过滤器
通过filterregistrationbean注册过滤器,指定拦截规则,与拦截器的放行/拦截逻辑一致:
import com.example.demo.filter.jwtfilter;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.web.servlet.filterregistrationbean;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
/**
* 过滤器配置:注册jwt过滤器
*/
@configuration
public class filterconfig {
@autowired
private jwtfilter jwtfilter;
@bean
public filterregistrationbean<jwtfilter> jwtfilterregistration() {
filterregistrationbean<jwtfilter> registrationbean = new filterregistrationbean<>();
registrationbean.setfilter(jwtfilter);
// 拦截所有接口
registrationbean.addurlpatterns("/*");
// 放行接口(与拦截器一致)
registrationbean.addinitparameter("excludedpaths", "/auth/login,/auth/register,/swagger-ui/**,/v3/api-docs/**");
registrationbean.setname("jwtfilter");
registrationbean.setorder(1); // 过滤器执行顺序,越小越先执行
return registrationbean;
}
}
拦截器与过滤器对比(选型建议)
| 对比维度 | 拦截器(handlerinterceptor) | 过滤器(filter) |
|---|---|---|
| 所属框架 | spring mvc | servlet |
| 执行时机 | 请求进入controller之前 | 请求进入servlet之前(更底层) |
| 依赖spring | 是,可直接注入spring bean(如jwtutil) | 否,需通过配置注入bean,稍繁琐 |
| 适用场景 | spring boot项目,需要结合spring生态(如权限注解) | 通用java web项目,无需依赖spring |
| 选型建议:spring boot项目优先使用拦截器,整合更顺畅,代码更简洁;非spring项目使用过滤器。 |
五、实战测试:接口权限校验效果
5.1 测试场景1:未携带令牌访问需要权限的接口
调用接口:http://localhost:8080/admin/user/list(假设是管理员接口),未在请求头携带authorization令牌,响应结果:
{
"code": 401,
"message": "未携带令牌,请先登录"
}5.2 测试场景2:携带无效令牌访问接口
请求头携带错误令牌(如随意输入字符串),响应结果:
{
"code": 401,
"message": "令牌无效或已过期,请重新登录"
}5.3 测试场景3:普通用户访问管理员接口
使用role=user的用户登录,获取令牌,携带令牌访问/admin/user/list接口,响应结果:
{
"code": 401,
"message": "权限不足,无法访问"
}5.4 测试场景4:携带有效令牌访问接口
使用role=admin的用户登录,获取令牌,在请求头添加:authorization: bearer 令牌,访问/admin/user/list接口,正常返回接口数据,校验通过。
六、常见问题与解决方案
令牌验证失败,提示“签名错误”?
解决方案:① 检查jwtutil中使用的密钥(secret)是否与配置文件一致;② 确认前端携带的令牌是否完整,无多余空格或字符;③ 检查令牌生成时的签名算法(本文用hs256)与验证时是否一致。
拦截器/过滤器未生效?
解决方案:① 检查拦截器/过滤器是否添加@component注解(注入spring容器);② 检查注册配置类(webmvcconfig/filterconfig)是否添加@configuration注解;③ 确认拦截规则是否正确,避免放行接口写错。
前端携带令牌后,后端仍提示“未携带令牌”?
解决方案:① 检查前端请求头字段名是否与配置文件中jwt.header一致(默认authorization);② 确认令牌格式是否正确(bearer + 空格 + 令牌);③ 排查跨域问题(若前后端分离,需配置跨域允许携带请求头)。
密码加密后,登录时校验失败?
解决方案:① 确认新增用户时,是否使用bcryptpasswordencoder加密密码;② 登录校验时,是否使用matches方法(明文密码与加密密码匹配),而非直接equals比较。
七、总结
本文完整实现了spring boot接口权限控制的核心流程:从用户登录接口设计、jwt令牌生成与验证,到拦截器/过滤器实现权限校验,完美解决“接口无安全控制”的问题,提升项目专业度。核心要点:
登录接口:核心是用户校验(用户名、密码、状态),密码必须加密存储,避免安全风险。
jwt工具类:封装生成、验证、解析令牌的核心方法,密钥和过期时间需配置化,便于维护。
权限校验:优先使用拦截器(spring boot适配更好),按需配置拦截/放行规则,支持角色权限区分。
掌握本文内容后,可直接将代码整合到毕设或实际项目中,实现接口的安全保护。后续可进一步扩展:如令牌刷新机制、更细粒度的权限控制(基于接口的权限分配)、异常统一处理等,让权限体系更完善。
到此这篇关于spring boot项目开发接口权限控制之登录+jwt实战指南的文章就介绍到这了,更多相关springboot接口权限控制内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论