0

0

Java中如何用Spring Security做权限控制

冰火之心

冰火之心

发布时间:2025-06-29 18:31:05

|

651人浏览过

|

来源于php中文网

原创

spring security实现权限控制的核心是认证和授权,其步骤如下:1. 添加spring-boot-starter-security依赖;2. 创建配置类继承websecurityconfigureradapter并重写configure方法设置访问规则,如permitall、hasrole等;3. 通过@preauthorize注解在controller层进行细粒度权限控制;4. 使用userdetailsservice接口从数据库加载用户信息,并配置passwordencoder加密密码;5. 自定义authenticationentrypoint和accessdeniedhandler处理认证失败和授权失败。整个流程确保用户身份验证和资源访问控制的安全性。

Java中如何用Spring Security做权限控制

Spring Security在Java应用中进行权限控制,核心在于认证(Authentication)和授权(Authorization)。认证确认用户的身份,授权决定用户可以访问哪些资源。

Java中如何用Spring Security做权限控制

解决方案

Java中如何用Spring Security做权限控制
  1. 添加依赖: 首先,在pom.xml文件中添加Spring Security的依赖。

    立即学习Java免费学习笔记(深入)”;

    
        org.springframework.boot
        spring-boot-starter-security
    
  2. 配置Spring Security: 创建一个配置类,继承WebSecurityConfigurerAdapter,并重写configure(HttpSecurity http)方法来配置安全规则。

    Java中如何用Spring Security做权限控制
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .antMatchers("/public/**").permitAll() // 允许所有用户访问
                    .antMatchers("/admin/**").hasRole("ADMIN") // 需要ADMIN角色
                    .anyRequest().authenticated() // 其他请求需要认证
                .and()
                .formLogin() // 使用表单登录
                    .permitAll()
                .and()
                .logout() // 允许注销
                    .permitAll();
        }
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                .withUser("user").password("{noop}password").roles("USER")
                .and()
                .withUser("admin").password("{noop}password").roles("ADMIN");
        }
    }

    这里使用了内存中的用户存储,实际项目中通常会使用数据库。{noop}表示密码未加密,生产环境必须使用加密算法。

  3. 定义用户角色和权限:configureGlobal方法中,定义了两个用户:useradmin,分别具有USERADMIN角色。

  4. Controller层权限控制: 在Controller层,可以使用@PreAuthorize注解进行更细粒度的权限控制。

    @RestController
    public class MyController {
    
        @GetMapping("/public/hello")
        public String publicHello() {
            return "Hello, public!";
        }
    
        @GetMapping("/admin/hello")
        @PreAuthorize("hasRole('ADMIN')")
        public String adminHello() {
            return "Hello, admin!";
        }
    
        @GetMapping("/user/hello")
        @PreAuthorize("hasRole('USER')")
        public String userHello() {
            return "Hello, user!";
        }
    }

    @PreAuthorize注解允许使用SpEL表达式进行权限判断,例如hasRole('ADMIN')表示需要ADMIN角色才能访问。

Spring Security如何与数据库集成?

Spring Security可以通过UserDetailsService接口与数据库集成。你需要创建一个类实现该接口,并重写loadUserByUsername方法,从数据库中加载用户信息。

析稿Ai写作
析稿Ai写作

科研人的高效工具:AI论文自动生成,十分钟万字,无限大纲规划写作思路。

下载
@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }
        return new org.springframework.security.core.userdetails.User(
            user.getUsername(), user.getPassword(), getAuthorities(user.getRoles()));
    }

    private Collection getAuthorities(List roles) {
        List authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }
}

然后,在SecurityConfig中配置使用自定义的UserDetailsService

@Autowired
private MyUserDetailsService userDetailsService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

这里使用了BCryptPasswordEncoder对密码进行加密。

如何实现更细粒度的权限控制,例如基于资源的权限?

除了基于角色的权限控制,Spring Security还支持基于资源的权限控制。可以使用@PreAuthorize注解结合SpEL表达式来实现。

例如,假设有一个Article类,每个Article都有一个author属性,只有文章的作者才能修改该文章。

@PutMapping("/articles/{id}")
@PreAuthorize("@articleService.isAuthor(principal.username, #id)")
public String updateArticle(@PathVariable Long id, @RequestBody Article article) {
    // ...
    return "Article updated";
}

这里,@articleService.isAuthor(principal.username, #id)表示调用articleServiceisAuthor方法,判断当前用户是否是文章的作者。principal.username表示当前登录用户的用户名,#id表示PathVariable中的id参数。

ArticleService的实现如下:

@Service
public class ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    public boolean isAuthor(String username, Long articleId) {
        Article article = articleRepository.findById(articleId).orElse(null);
        if (article == null) {
            return false;
        }
        return article.getAuthor().equals(username);
    }
}

如何处理认证失败和授权失败的情况?

Spring Security提供了多种方式来处理认证失败和授权失败的情况。

  • 认证失败: 可以配置自定义的AuthenticationEntryPoint来处理认证失败的情况。例如,可以返回一个401 Unauthorized错误。
  • 授权失败: 可以配置自定义的AccessDeniedHandler来处理授权失败的情况。例如,可以返回一个403 Forbidden错误。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and()
            .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler)
            .and()
            .formLogin()
                .permitAll()
            .and()
            .logout()
                .permitAll();
    }
}

可以自定义AuthenticationEntryPointAccessDeniedHandler来实现不同的处理逻辑。例如,可以记录日志、跳转到错误页面等。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

841

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

742

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

737

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.8万人学习

PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

ThinkPHP6.x 微实战--十天技能课堂
ThinkPHP6.x 微实战--十天技能课堂

共26课时 | 1.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号