记录–权限认证
-
- why:不管是什么系统或者项目,第一步都是认证和授权。
-
- 核心定位
- 一、权限认证的核心基础组件(必懂,落地的基石)
-
- 1. 核心实体
- 2. 核心关联关系(多对多为主,企业设计的通用范式)
- 3. 易忽略的核心分类:功能权限 vs 数据权限
- 二、权限认证的核心执行流程(一次请求的完整链路)
-
- 关键步骤拆解
- 三、Java后端主流权限认证方案(分场景,选对不选贵)
-
- 方案1:Session-Cookie模式(传统单体项目首选,最简单)
-
- 核心原理
- 核心实现
- 优缺点&适用场景
- 集群适配:Session共享
- 方案2:Token模式(分布式/微服务首选,目前最主流)
-
- 核心原理
- 核心实现:JWT(JSON Web Token)
-
- 1. JWT的结构(三段式,以`.`分隔,都是Base64编码)
- 2. JWT的核心特点
- 优缺点&适用场景
- 企业级优化:JWT+Redis(解决JWT的致命缺点)
- 方案3:OAuth2.0(开放平台/第三方登录首选)
-
- 核心定位
- 常见场景
- 4种授权模式(企业开发重点掌握2种)
- 方案4:SSO单点登录(多系统统一登录首选)
-
- 核心定位
- 常见场景
- 核心原理(基于Token/OAuth2.0实现)
- 主流实现
- 四、Java后端权限认证主流框架(落地必用,二选一即可)
-
- 1. 框架对比(选对框架,减少开发成本)
- 2. 新手入门建议
- 3. 框架核心落地要点(以Spring Security为例,最主流)
-
- (1)核心依赖(Spring Boot自动配置)
- (2)核心配置:自定义用户认证、权限规则
- (3)常用注解(方法级权限校验,细粒度控制)
- 五、企业级权限体系的设计要点(从“能用”到“好用”,面试高频)
-
- 1. 权限粒度设计:粗粒度→细粒度,按需选择
- 2. 权限动态配置(无需重启服务)
- 3. 高性能优化:缓存是核心
- 4. 数据权限的企业级实现(重点,初级开发的短板)
- 5. 安全加固(避免常见漏洞)
- 6. 微服务下的权限认证架构(网关统一认证)
- 六、开发/面试中常见的问题&解决方案(避坑指南)
-
- 1. JWT如何实现刷新Token?
- 2. 如何实现接口的匿名访问/免登访问?
- 3. 前后端分离项目中,跨域问题如何解决?
- 4. 密码加密后,如何做密码校验?
- 七、学习提升路径(适配你的实际水平,循序渐进)
-
- 阶段1:基础落地(1-2周)
- 阶段2:企业实战(2-3周)
- 阶段3:架构提升(1个月)
- 阶段4:面试准备
- 总结
这是记录系列的文章,
我自己工作也有好几年了,平时也会写一些不成文的小总结,但是都比较零散。现在准备再次找工作,借这次机会,将自己所学的全部内容都总结一遍,记录下来。
why:不管是什么系统或者项目,第一步都是认证和授权。
核心定位
权限认证是系统安全的第一道也是核心防线,本质解决两个核心问题:
所有权限体系的设计,都是围绕这两个问题展开,后续的框架、方案都是这两个问题的工程化实现。
一、权限认证的核心基础组件(必懂,落地的基石)
这是构建权限体系的“原子单元”,初级开发最容易混淆组件关系,导致后续设计混乱,先把这层掰透。
1. 核心实体
| 用户(User) | 系统的操作主体 | 手机号/账号、用户ID、昵称 |
| 角色(Role) | 权限的“集合容器” | 管理员、普通用户、运营、财务 |
| 权限(Permission) | 系统最小的操作许可 | 查看订单、删除用户、导出数据 |
| 资源(Resource) | 权限对应的操作对象 | 接口(/api/order/delete)、菜单(订单管理)、按钮(删除按钮)、数据(某部门的订单) |
2. 核心关联关系(多对多为主,企业设计的通用范式)
用户-角色:多对多 → 一个用户可拥有多个角色(比如某员工是“运营+普通用户”),一个角色可分配给多个用户; 角色-权限:多对多 → 一个角色可拥有多个权限(比如“管理员”有“增删改查用户”所有权限),一个权限可分配给多个角色(比如“查看订单”可分配给运营和财务); 权限-资源:一对一/多对一 → 一个权限对应一个具体资源(比如“删除订单”权限对应/api/order/delete接口)。
3. 易忽略的核心分类:功能权限 vs 数据权限
初级开发通常只做功能权限,但企业开发中数据权限是面试/工作的高频考点,也是系统安全的关键:
- 功能权限:控制“能不能操作某个功能”(比如能不能点删除按钮、能不能调用删除接口);
- 数据权限:控制“能操作哪些范围的数据”(比如运营只能看自己负责区域的订单,管理员能看所有订单;财务能看订单金额,运营不能看)。
二、权限认证的核心执行流程(一次请求的完整链路)
不管是单体项目还是分布式项目,一次用户请求的权限校验链路是固定的,理解这个流程,后续看框架源码、排查问题都会事半功倍,以Java Web项目为例:
用户发起请求(如点击删除订单)→ 前端携带认证凭证(Token/SessionId)→ 后端入口(网关/过滤器/拦截器)→ 身份认证 → 权限校验(功能+数据)→ 资源访问(调用业务接口)→ 返回响应结果
关键步骤拆解
三、Java后端主流权限认证方案(分场景,选对不选贵)
根据项目架构(单体/分布式/微服务)和业务场景(内部系统/外部开放平台/第三方登录),选择不同的方案,以下是企业开发中99%会用到的核心方案,从简单到复杂排序,适配你的实际开发水平。
方案1:Session-Cookie模式(传统单体项目首选,最简单)
核心原理
核心实现
- 基于Java Web原生API(HttpSession、Cookie),无需额外框架,新手可快速落地;
- 权限校验可通过Filter(过滤器) 实现:拦截所有请求,解析SessionId,校验用户权限。
优缺点&适用场景
| 实现简单,无额外依赖 | 服务端内存存储Session,集群下需做Session共享(如Redis);跨域问题(Cookie默认不支持跨域);易受CSRF攻击 | 小型单体内部系统(如公司后台、小工具),用户量<10万,无跨域需求 |
集群适配:Session共享
单体项目扩容为集群后,多台服务端的内存Session不互通,需通过Redis实现Session共享:
- 服务端将Session数据存入Redis,以SessionId为Key;
- 所有服务端统一从Redis中获取Session,解决集群一致性问题。
方案2:Token模式(分布式/微服务首选,目前最主流)
核心原理
核心实现:JWT(JSON Web Token)
Token模式的工业标准,Java开发中几乎所有Token方案都是基于JWT实现,必须掌握。
1. JWT的结构(三段式,以.分隔,都是Base64编码)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwOTYwMH0.Sf98Rf8XU07p2h5eQa9Z7k8L9M0N1O2P3Q4R5S6T7U8V9W0X1Y2Z3
- 头部(Header):指定加密算法(如HS256)和令牌类型(JWT);
- 载荷(Payload):存储用户核心信息(自定义,如用户ID、角色)和标准声明(如过期时间exp);
- 签名(Signature):将头部+载荷拼接,用服务端秘钥加密生成,用于验证Token是否被篡改。
2. JWT的核心特点
- 无状态:服务端无需存储Token,仅通过秘钥验证,适配分布式/微服务(多台服务端共用一个秘钥即可);
- 自包含:Token中携带了用户核心信息,服务端无需每次查询数据库,提升性能。
优缺点&适用场景
| 无状态,适配分布式/微服务;支持跨域;无CSRF风险 | Token无法主动注销(一旦生成,只能等过期);载荷是Base64编码(非加密,不能存敏感信息如密码);Token过长会增加请求开销 | 分布式/微服务项目、跨域项目、移动端项目(APP/小程序),用户量不限 |
企业级优化:JWT+Redis(解决JWT的致命缺点)
JWT无法主动注销是最大问题(比如用户退出登录、账号被封,Token仍能使用),企业中通过Redis弥补:
方案3:OAuth2.0(开放平台/第三方登录首选)
核心定位
OAuth2.0不是一个认证方案,而是一个授权框架,解决的核心问题:第三方应用在不获取用户账号密码的情况下,获取系统的有限授权。
常见场景
- 第三方登录:微信登录、支付宝登录、QQ登录(你的系统无需存储微信用户的账号密码,通过微信授权即可获取用户信息);
- 开放平台:比如微信支付开放平台、抖音开放平台,第三方开发者可通过OAuth2.0获取平台的接口授权。
4种授权模式(企业开发重点掌握2种)
OAuth2.0定义了4种授权模式,根据安全性要求和使用场景选择,Java开发中最常用的是授权码模式和密码模式:
方案4:SSO单点登录(多系统统一登录首选)
核心定位
解决多系统之间的统一登录问题:用户在一个系统登录后,无需在其他关联系统重复登录,一次登录,全网通行。
常见场景
企业内部的多个系统(如OA系统、CRM系统、财务系统),都属于同一个企业域,需要统一的身份认证。
核心原理(基于Token/OAuth2.0实现)
主流实现
- 基于OAuth2.0的授权码模式实现(最常用,企业级首选);
- 开源框架:CAS(Central Authentication Service),可快速搭建SSO认证中心。
四、Java后端权限认证主流框架(落地必用,二选一即可)
实际开发中不会手写权限体系,都是基于成熟框架二次开发,Java生态中权限框架只有两个主流选择:Spring Security 和 Apache Shiro,无需学其他框架,掌握其一即可,企业中Spring Security占比更高(适配Spring Boot/Spring Cloud)。
1. 框架对比(选对框架,减少开发成本)
| 生态适配 | 与Spring Boot/Spring Cloud深度集成,自动配置,无额外依赖 | 与Spring生态兼容,但需手动配置,也支持非Spring项目 |
| 学习曲线 | 较陡(概念多,源码复杂) | 平缓(API简单,上手快,适合新手) |
| 功能覆盖 | 功能全面(认证、授权、防csrf、防刷、OAuth2.0、SSO) | 核心功能完善(认证、授权、会话管理),高级功能(OAuth2.0/SSO)需集成第三方插件 |
| 分布式适配 | 原生支持分布式,可结合JWT/Redis实现 | 需手动集成JWT/Redis,适配分布式 |
| 适用场景 | Spring Boot/Spring Cloud微服务项目、企业级大型项目 | 单体项目、小型分布式项目、新手入门 |
2. 新手入门建议
- 如果你是Spring Boot/Cloud技术栈,直接学Spring Security(企业面试高频考点,生态适配性最好);
- 如果你想快速落地单体项目,先学Shiro(上手快,API简单,能快速完成权限开发)。
3. 框架核心落地要点(以Spring Security为例,最主流)
Spring Security的核心是过滤器链(所有认证/授权逻辑都是通过过滤器实现),新手只需掌握核心配置+常用注解,即可完成80%的开发需求:
(1)核心依赖(Spring Boot自动配置)
<!– Spring Security核心依赖 –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!– 结合JWT –>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
(2)核心配置:自定义用户认证、权限规则
通过SecurityConfig配置类,实现用户信息查询、密码加密、接口权限规则:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
// 注入用户详情服务(自定义用户信息查询,从数据库查)
@Autowired
private UserDetailsService userDetailsService;
// 密码加密器(Spring Security要求必须加密,不能明文存储)
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 核心过滤器链配置
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 关闭csrf(前后端分离项目可关闭,单体项目建议开启)
.csrf(csrf -> csrf.disable())
// 配置接口权限规则
.authorizeHttpRequests(auth -> auth
// 放行登录接口、静态资源
.requestMatchers("/api/user/login").permitAll()
// 管理员才能访问的接口
.requestMatchers("/api/admin/**").hasRole("ADMIN")
// 拥有指定权限才能访问的接口
.requestMatchers("/api/order/delete").hasAuthority("order:delete")
// 其他所有接口都需要认证
.anyRequest().authenticated()
)
// 自定义登录逻辑(替换默认登录页)
.formLogin(form -> form.loginProcessingUrl("/api/user/login").permitAll())
// 异常处理(401/403自定义返回)
.exceptionHandling(ex -> ex
.authenticationEntryPoint((req, res, e) -> res.sendError(401, "未认证"))
.accessDeniedHandler((req, res, e) -> res.sendError(403, "无权限"))
);
return http.build();
}
// 配置用户详情服务和密码加密器
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
}
(3)常用注解(方法级权限校验,细粒度控制)
在业务层方法上添加注解,实现更细粒度的权限控制,需在启动类添加@EnableGlobalMethodSecurity开启:
@SpringBootApplication
// 开启方法级权限校验
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- @PreAuthorize("hasRole('ADMIN')"):方法执行前校验角色;
- @PreAuthorize("hasAuthority('order:delete')"):方法执行前校验权限;
- @Secured("ROLE_ADMIN"):简化版角色校验(需加ROLE_前缀)。
示例:
@Service
public class OrderService {
// 只有拥有order:delete权限的用户才能执行
@PreAuthorize("hasAuthority('order:delete')")
public void deleteOrder(Long id) {
// 业务逻辑
}
}
五、企业级权限体系的设计要点(从“能用”到“好用”,面试高频)
初级开发能实现基础的认证授权,但企业级项目要求权限体系可扩展、可配置、高性能、高安全,以下是架构设计的核心要点,也是面试中架构师级别的考察点,你需要重点理解并在项目中落地。
1. 权限粒度设计:粗粒度→细粒度,按需选择
- 粗粒度权限:基于角色控制(如hasRole('ADMIN')),适合小型系统,配置简单;
- 细粒度权限:基于权限标识控制(如hasAuthority('order:delete:1001')),适合中大型系统,支持精细化控制(比如某个用户只能删除自己的订单);
- 企业建议:角色+权限结合,角色作为权限的集合,同时支持给用户单独分配权限(突破角色的限制,比如给某个普通用户临时分配“导出数据”权限)。
2. 权限动态配置(无需重启服务)
初级开发常把权限规则写死在代码中(如hasRole('ADMIN')),企业中要求后台管理系统可视化配置,无需重启服务:
3. 高性能优化:缓存是核心
权限校验是高频操作(每个请求都要做),如果每次都查询数据库,会严重影响性能,企业中必做缓存优化:
- 登录成功后,将用户的权限信息存入Redis,设置过期时间(如2小时);
- 权限配置变更后,主动刷新该用户的缓存;
- 缓存过期后,从数据库重新查询并刷新缓存。
4. 数据权限的企业级实现(重点,初级开发的短板)
数据权限是企业开发的核心需求,也是面试高频考点,主流实现方式是MyBatis拦截器+注解,无需在每个业务方法中手动过滤数据:
示例:
// 自定义数据权限注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataPermission {
// 数据范围:DEPT(本部门)、ALL(所有)、SELF(自己)
String scope() default "SELF";
}
// 业务层使用
@Service
public class OrderService {
@DataPermission(scope = "DEPT")
public List<Order> listOrder() {
// 无需手动加where条件,MyBatis拦截器会动态改写SQL
return orderMapper.selectList(null);
}
}
5. 安全加固(避免常见漏洞)
- 密码安全:必须加密存储(使用BCrypt/SHA256),禁止明文存储;添加密码复杂度校验(如6-20位,包含字母数字);
- Token安全:JWT的秘钥要复杂(避免被破解);Token放在请求头中(避免XSS攻击);设置合理的过期时间(如2小时),配合刷新Token机制;
- 防CSRF:单体项目开启Spring Security的CSRF防护,前后端分离项目可关闭(Token模式无CSRF风险);
- 防刷限流:结合网关(如Spring Cloud Gateway)对接口做限流(如每个用户每分钟最多请求100次),防止恶意请求;
- 日志审计:记录所有权限相关操作(如用户登录、角色分配、权限变更、敏感接口访问),方便问题排查和安全审计。
6. 微服务下的权限认证架构(网关统一认证)
微服务项目中,不建议每个服务都做独立的权限认证,否则会导致配置冗余、维护困难,主流方案是网关统一认证+服务端细粒度授权:
六、开发/面试中常见的问题&解决方案(避坑指南)
1. JWT如何实现刷新Token?
- 方案:双Token机制(访问Token+刷新Token);
- 实现:
- 登录成功后,生成短有效期的访问Token(如2小时,用于接口访问)和长有效期的刷新Token(如7天,用于刷新访问Token);
- 访问Token过期后,前端用刷新Token调用刷新接口,服务端验证刷新Token有效后,生成新的访问Token返回;
- 刷新Token过期后,要求用户重新登录。
2. 如何实现接口的匿名访问/免登访问?
- Spring Security:通过requestMatchers("/api/xxx").permitAll()放行指定接口;
- Shiro:通过filterChainDefinitionMap.put("/api/xxx", "anon")配置匿名访问。
3. 前后端分离项目中,跨域问题如何解决?
- 后端配置CORS(跨域资源共享),允许前端域名的请求;
- Spring Boot中可通过配置类快速实现:@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 允许前端域名(*表示允许所有,生产环境建议指定具体域名)
config.addAllowedOrigin("http://localhost:8080");
// 允许所有请求方法(GET/POST/DELETE等)
config.addAllowedMethod("*");
// 允许所有请求头(包括Token头)
config.addAllowedHeader("*");
// 允许携带Cookie
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 对所有接口生效
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
4. 密码加密后,如何做密码校验?
- 不能对用户输入的密码再次加密后对比,而是通过密码加密器的matches方法校验(BCryptPasswordEncoder会自动生成随机盐,每次加密结果不同,但matches方法能验证);
- 示例:// 密码加密器
PasswordEncoder encoder = new BCryptPasswordEncoder();
// 加密密码(存储到数据库)
String encodePwd = encoder.encode("123456");
// 校验密码(用户输入的密码 + 数据库中的加密密码)
boolean isMatch = encoder.matches("123456", encodePwd); // true
七、学习提升路径(适配你的实际水平,循序渐进)
你有6年工作经验,面试时会被考察架构思维,但实际水平1年,建议按以下路径学习,先落地再深入,避免眼高手低:
阶段1:基础落地(1-2周)
阶段2:企业实战(2-3周)
阶段3:架构提升(1个月)
阶段4:面试准备
总结
权限认证的核心永远是认证(你是谁) 和授权(你能做什么),所有的方案、框架、架构都是这两个问题的工程化实现。作为Java后端开发,你不需要掌握所有细节,但必须做到:
按以上路径学习,你能快速弥补权限认证的知识短板,既满足实际开发需求,又能应对面试中的架构考察。



