当前位置: 代码网 > it编程>编程语言>Java > Spring Security 框架最佳实践

Spring Security 框架最佳实践

2025年11月21日 Java 我要评论
一、什么是 spring security?spring security 是一个功能强大、高度可定制的身份验证(authentication)和访问控制(authorization)框架,是保护基于

一、什么是 spring security?

spring security 是一个功能强大、高度可定制的身份验证(authentication)和访问控制(authorization)框架,是保护基于 spring 的应用的事实标准。

✅ 核心功能:

  • 用户登录认证(authentication)
  • 权限控制、角色控制(authorization)
  • 防止 csrf、会话固定、点击劫持等攻击
  • 支持多种登录方式:表单登录、http basic、oauth2、jwt、ldap 等
  • 与 spring boot 无缝集成

二、spring security 核心概念

1.authentication(认证)

  • 代表“当前用户是谁”,包含用户名、密码、权限等。
  • 由 authenticationmanager 管理认证过程。

2.userdetails&userdetailsservice

  • userdetails:封装用户信息(用户名、密码、权限、是否锁定等)
  • userdetailsservice:根据用户名加载 userdetails
@override
public userdetails loaduserbyusername(string username) {
    // 从数据库查用户 → 返回 userdetails(含加密密码 + 权限)
}

3.passwordencoder

  • 用于加密密码和比对密码。
  • 永远不要存储明文密码!
  • 常用实现:bcryptpasswordencoderscryptpasswordencoderpbkdf2passwordencoder
// 注册时:
user.setpassword(passwordencoder.encode(rawpassword));
// 登录时(框架自动调用):
passwordencoder.matches(rawpassword, encodedpassword); // true/false

4.grantedauthority

  • 代表一个权限,如 "role_admin""user:delete"
  • 通常以 role_ 开头表示角色,其它表示具体权限。

5.securitycontext&securitycontextholder

  • 存储当前登录用户的信息(authentication 对象)。
  • 可在任何地方获取当前用户:
authentication auth = securitycontextholder.getcontext().getauthentication();
string username = auth.getname();

三、spring security 工作流程(认证过程)

sequencediagram
    participant user
    participant filter as filterchain (spring security)
    participant provider as authenticationprovider
    participant service as userdetailsservice
    participant encoder as passwordencoder
    user->>filter: 提交用户名/密码
    filter->>provider: 调用 authenticate()
    provider->>service: loaduserbyusername(username)
    service-->>provider: 返回 userdetails(含加密密码)
    provider->>encoder: matches(输入密码, 数据库加密密码)
    alt 匹配成功
        encoder-->>provider: true
        provider-->>filter: 返回认证成功 authentication
        filter->>user: 登录成功,跳转
    else 匹配失败
        encoder-->>provider: false
        provider-->>filter: 抛出异常
        filter->>user: 登录失败
    end

四、常用配置方式(spring boot)

1. 引入依赖(maven)

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-security</artifactid>
</dependency>

2. 基础配置类(启用 web 安全)

@configuration
@enablewebsecurity
public class securityconfig {
    @bean
    public securityfilterchain filterchain(httpsecurity http) throws exception {
        http
            .authorizehttprequests(authz -> authz
                .requestmatchers("/login", "/register", "/css/**").permitall()
                .requestmatchers("/admin/**").hasrole("admin")
                .requestmatchers("/user/**").hasanyrole("user", "admin")
                .anyrequest().authenticated()
            )
            .formlogin(form -> form
                .loginpage("/login")           // 自定义登录页
                .defaultsuccessurl("/home")    // 登录成功跳转
                .permitall()
            )
            .logout(logout -> logout
                .logoutsuccessurl("/login?logout")
                .permitall()
            );
        return http.build();
    }
    @bean
    public passwordencoder passwordencoder() {
        return new bcryptpasswordencoder(); // 推荐使用 bcrypt
    }
}

3. 自定义 userdetailsservice

@component
public class myuserserviceimpl implements userdetailsservice {
    @autowired
    private usermapper usermapper;
    @override
    public userdetails loaduserbyusername(string username) throws usernamenotfoundexception {
        user user = usermapper.finduserbyname(username);
        if (user == null) throw new usernamenotfoundexception("用户不存在");
        // ✅ 直接返回数据库中的加密密码(注册时已加密存储!)
        return user.builder()
            .username(user.getusername())
            .password(user.getsupwd()) // ← 不要再 encode!
            .roles("user") // 或者 .authorities(getauthorities())
            .build();
    }
}

五、权限控制(授权 authorization)

1. 方法级别权限(推荐)

@service
public class articleservice {
    @preauthorize("hasrole('admin')") // 需要 admin 角色
    public void deletearticle(long id) {
        // ...
    }
    @preauthorize("hasauthority('article:edit')") // 需要具体权限
    public void editarticle(article article) {
        // ...
    }
    @postauthorize("returnobject.owner == authentication.name")
    public article getarticle(long id) {
        // 返回后检查:只有文章主人才能看
    }
}

⚠️ 要启用方法级权限,需在配置类加:@enablemethodsecurity

@configuration
@enablewebsecurity
@enablemethodsecurity // ← 启用 @preauthorize 等注解
public class securityconfig { ... }

2. 页面级别权限(thymeleaf)

<!-- 只有 admin 能看到 -->
<div sec:authorize="hasrole('admin')">
    <a href="/admin" rel="external nofollow" >管理后台</a>
</div>
<!-- 显示当前用户名 -->
<span sec:authentication="name"></span>

需引入:

<dependency>
    <groupid>org.thymeleaf.extras</groupid>
    <artifactid>thymeleaf-extras-springsecurity6</artifactid>
</dependency>

六、常见自定义扩展

1. 自定义登录成功/失败处理器

@component
public class myauthenticationsuccesshandler implements authenticationsuccesshandler {
    @override
    public void onauthenticationsuccess(httpservletrequest request, 
                                        httpservletresponse response, 
                                        authentication authentication) throws ioexception {
        response.sendredirect("/home?loginsuccess");
    }
}

在配置中使用:

.formlogin(form -> form
    .successhandler(mysuccesshandler)
    .failurehandler(myfailurehandler)
)

2. 自定义权限异常处理

@component
public class myaccessdeniedhandler implements accessdeniedhandler {
    @override
    public void handle(httpservletrequest request, httpservletresponse response, accessdeniedexception accessdeniedexception) throws ioexception {
        response.sendredirect("/403");
    }
}

配置:

.exceptionhandling(ex -> ex
    .accessdeniedhandler(myaccessdeniedhandler)
)

七、与 jwt / 前后端分离集成(简要)

如果你是前后端分离项目(如 vue + spring boot),通常不用 session,改用 jwt:

  1. 用户 post /login 提交用户名密码
  2. 后端验证成功 → 生成 jwt token 返回
  3. 前端后续请求在 header 中携带 authorization: bearer <token>
  4. 后端用 filter 解析 token → 设置 securitycontext

⚠️ 此时 userdetailsservice 依然有用 —— 用于从 token 中的用户名加载用户权限!

八、最佳实践 & 注意事项

项目建议
密码存储必须加密(bcrypt 最常用)
密码比对交给 spring security,不要手动比对
权限设计角色(role_) + 细粒度权限(user:delete)结合
登录页可自定义,但路径要 permitall
csrf表单登录默认开启,jwt 项目可关闭
调试可临时 .authorizehttprequests(authz -> authz.anyrequest().permitall()) 放行所有

✅ 总结一句话:

spring security = 认证(你是谁)+ 授权(你能干什么)+ 安全防护,你只需要提供“用户数据”和“权限规则”,框架自动完成验证和拦截。

📚 学习路径建议:

  1. 先跑通表单登录 + 自定义 userdetailsservice
  2. 学会配置 url 权限控制
  3. 掌握方法级权限 @preauthorize
  4. 学习自定义处理器(登录成功/失败、无权限)
  5. 进阶:jwt、oauth2、方法权限表达式、动态权限

💡 送你一个完整可运行的最小示例结构:

src/
├── controller/
│   └── logincontroller.java       // 登录页、首页
├── service/
│   └── myuserserviceimpl.java     // loaduserbyusername
├── config/
│   └── securityconfig.java        // 权限配置 + passwordencoder
└── entity/
    └── user.java                  // 用户实体(含加密密码字段)

到此这篇关于spring security 框架的文章就介绍到这了,更多相关spring security 框架内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com