Skip to content

认证和授权的区别是什么?Spring Security 分别是怎么实现的? ​

  • 标签:Spring Security、认证授权、后端

🏛 业务架构师 ​

一句话区分:认证(Authentication)回答"你是谁",授权(Authorization)回答"你能干什么"。两道关卡先后执行——先验明正身,再核对权限。

Spring Security 的实现分工:

认证:

  • 入口:认证过滤器(表单登录、HTTP Basic、Bearer Token 解析等);
  • 核心:AuthenticationManager → ProviderManager → AuthenticationProvider(如 DaoAuthenticationProvider 查库+BCrypt 比对密码);
  • 产出:Authentication 对象(身份+权限)存 SecurityContextHolder(ThreadLocal);失败 → 401。

授权:

  • URL 级:AuthorizationFilter 按配置规则(/admin/** 需要 ADMIN 角色)——粗粒度的入口控制;
  • 方法级:@PreAuthorize("hasAuthority('order:delete')") AOP 拦截——细粒度的业务动作控制,支持 SpEL(参数校验:@PreAuthorize("#userId == authentication.name") 防水平越权);
  • 失败 → 403。

业务视角的架构要点:

  1. 粒度选择:URL 级管"菜单/入口",方法级管"按钮/操作",数据级(行级权限)要在 Service 里显式控制——三层权限模型对应 RBAC 的落地分层;
  2. 常见事故源:只做了认证没做授权(登录了就能调所有接口)——尤其内部管理端对接外部 API 时忘配规则,默认应该是 deny-all 再按需放开(最小权限原则);
  3. 越权是授权问题不是认证问题——水平越权(改别人订单)要用方法级+数据级双重防护,这是安全审计的高频项。

安全设计的第一课就是把这两个概念分开建模——混为一谈的系统几乎必然出越权事故。

🏗 系统架构师 ​

认证(Authentication)= 你是谁——验证身份(密码、JWT 签名、OAuth2 授权码、生物特征);授权(Authorization)= 你能干什么——验证权限(角色、权限点、资源归属)。先认证后授权,两阶段有先后依赖。

Spring Security 的实现(两套机制各管一段):

认证侧:

  • 入口过滤器:表单(UsernamePasswordAuthenticationFilter)、HTTP Basic、JWT 解析过滤器(自定义 OncePerRequestFilter)、OAuth2 login/resource server;
  • 核心:AuthenticationManager → ProviderManager → AuthenticationProvider(DaoAuthenticationProvider 查库验密);
  • 产出:Authentication 对象(principal + credentials + authorities)存入 SecurityContextHolder(ThreadLocal)。

授权侧(两个层次):

  • URL 级:AuthorizationFilter + authorizeHttpRequests——粗粒度入口控制(/admin/** 要 ADMIN);
  • 方法级:@PreAuthorize/@PostAuthorize(AOP 切面)——业务级精细控制(@PreAuthorize("#orderId == authentication.name or hasRole('ADMIN')",SpEL 引用参数做数据级判断)。

架构师视角的分层纪律:

  • URL 级做粗防线(挡明显越界),方法级做业务规则(谁能操作哪条数据)——两层都要有:只靠 URL 前缀判断是脆弱的(新端点漏配即裸奔),只靠方法级则攻击面暴露过多;
  • 授权判断要基于服务端会话/令牌状态,绝不信任请求参数里的角色字段(客户端可伪造);
  • 权限模型演进:URL/方法级硬编码 → RBAC 角色 → 数据级 ABAC/策略引擎(业务复杂后权限外置成策略服务)——权限的复杂度要匹配业务,警惕框架特性诱发的过度设计。

💻 全栈开发专家 ​

认证(Authentication):你是谁——验证身份(用户名密码、JWT、OAuth2、短信码)。 授权(Authorization):你能干什么——验证权限(角色、ACL、资源归属)。

先认证后授权:没有身份就无从谈权限。

Spring Security 的实现分工:

认证侧:

java
http.formLogin(withDefaults())                    // 表单
    .oauth2ResourceServer(o -> o.jwt(...))        // JWT
// 或自定义 provider:
auth.providerManager(new DaoAuthenticationProvider()...)
  • 流程:Filter 拦截 → AuthenticationManager/Provider 认证 → 结果放 SecurityContextHolder(ThreadLocal,请求级);
  • 密码校验:PasswordEncoder(BCrypt)在 DaoAuthenticationProvider 内完成。

授权侧(三层):

  1. URL 级(粗粒度):
java
http.authorizeHttpRequests(a -> a
    .requestMatchers("/admin/**").hasRole("ADMIN")
    .requestMatchers("/order/**").hasAuthority("order:read")
    .requestMatchers(HttpMethod.PUT, "/api/**").authenticated()
    .anyRequest().permitAll());
  1. 方法级(细粒度,需 @EnableMethodSecurity):
java
@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
public Order orderOf(Long userId) { ... }        // SpEL 可拿参数,防水平越权神器
  1. 领域对象级(ACL/手写):资源属于谁——@PostAuthorize("returnObject.owner == authentication.name") 或业务层判 ownership。

架构上的落点:认证产物 Authentication(含 authorities)是两层的衔接——授权只消费「身份+权限集合」,不关心怎么认证的。实战经验:URL 层做面(拦未登录),方法层做点(业务权限+数据归属),只靠 URL 匹配做授权的系几乎必然出越权漏洞——路径和业务权限对不上太容易了。