Spring Security 入门与实战指南(第三版)

注:完整笔记可在 https://github.com/WuSangui571/SpringSecurity 中的 README.md 文件浏览,此处发表的是经由 GPT 润色过的精简版。

第 7 章 权限管理

Spring Security 支持两种方式的权限控制:基于角色(Role)和基于资源(Permission)管理。

7.1 数据库表设计

推荐经典五表模型:

  • t_user(用户表)

  • t_role(角色表,字段:id, role, role_name)

  • t_permission(权限表,字段:id, name, code, url, type, parent_id, order_no, icon)

  • t_user_role(用户-角色关联表)

  • t_role_permission(角色-权限关联表)

7.2 基于角色的权限管理

  1. 用户登录:前面章节已实现。

  2. 加载角色:在 loadUserByUsername 中查询用户对应角色:

    List<TRole> roles = tRoleMapper.selectByUserId(tUser.getId());
    tUser.setTRoleList(roles);
  1. 在实体中返回权限:让 TUsergetAuthorities() 返回角色列表:

    @Override @JsonIgnore
    public Collection extends GrantedAuthority> getAuthorities() {
       return tRoleList.stream()
          .map(role -> new SimpleGrantedAuthority(role.getRole()))
          .collect(Collectors.toList());
    }
  2. 开启方法级安全:在配置类上添加:

    @EnableMethodSecurity(prePostEnabled = true)
    public class SecurityConfig { }
  3. 使用注解拦截:如:

    @PreAuthorize("hasAuthority('admin')")
    public String secureEndpoint() { }
  4. 自定义 403 页面:在 src/main/resources/static/error/403.html 放置自定义页面。

7.3 基于资源(Permission)管理

  1. 修改实体:删除角色字段,新增 List tPermissionList,在 getAuthorities() 返回 code

    @Override @JsonIgnore
    public Collection extends GrantedAuthority> getAuthorities() {
       return tPermissionList.stream()
          .map(p -> new SimpleGrantedAuthority(p.getCode()))
          .collect(Collectors.toList());
    }
  2. 加载权限:在 loadUserByUsername 中替换角色查询为权限查询:

    List<TPermission> perms = tPermissionMapper.selectByUserId(tUser.getId());
    tUser.setTPermissionList(perms);
  3. 注解使用

    @PreAuthorize("hasAuthority('clue:list')")
    public String clueList(){ }

结构与基于角色几乎一致,只将权限表达改为 code 值。

第 8 章 前后端分离登录认证

8.1 项目拆分与跨域配置

  • 后端:Spring Boot + Spring Security,无页面返回,仅提供 JSON 接口。

  • 前端:Vue 或简单 HTML + Axios,通过 CORS 访问后端。

@Bean
public CorsConfigurationSource corsConfigurationSource() { }

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 return http
  .csrf(csrf -> csrf.disable())
  .cors(cors -> cors.configurationSource(corsConfigurationSource()))
  .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  .formLogin(form -> form.loginProcessingUrl("/user/login")
    .successHandler(mySuccessHandler)
    .failureHandler(myFailureHandler))
  .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
  .build();
}

8.2 自定义登录处理

  • 前端:使用 FormData 提交用户名/密码:

    let form = new FormData();
    form.append('username', user);
    form.append('password', pwd);
    axios.post('/user/login', form);
  • 成功回调:实现 AuthenticationSuccessHandler,返回统一结构:

    response.setContentType("application/json;charset=UTF-8");
    response.getWriter().write(new ObjectMapper().writeValueAsString(R.ok(auth)));
  • 失败回调:同理实现 AuthenticationFailureHandler

8.3 会话与退出

  • 无状态:禁用 Session/Cookie,依赖 JWT(下一章):

    .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  • 退出:自定义 LogoutSuccessHandler

    .logout(logout -> logout.logoutUrl("/user/logout")
    .logoutSuccessHandler(myLogoutHandler))

前端点击退出调用 /user/logout 即可。


  • 微信
  • 赶快加我聊天吧
  • QQ
  • 赶快加我聊天吧
  • weinxin
三桂

发表评论 取消回复 您未登录,登录后才能评论,前往登录