程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

Spring Security -- 权限控制(转载)

Spring Security权限控制可以配合授权注解使用,Spring Security提供了三种不同的安全注解:

  • Spring Security自带的@Secured注解;
  • JSR-250的@DenyAll、@RolesAllowed、@PermitAll注解;
  • 表达式驱动的注解,包括@PreAuthorize、@PostAuthorize、@PreFilter和 @PostFilter;

一、权限控制注解

1、@Secured注解

在方法上指定安全性要求,只有对应角色的用户才可以调用这些方法:

复制代码
import org.springframework.security.access.annotation.Secured;
 
 
public interface UserService {
 
    List<User> findAllUsers();
 
    @Secured("ROLE_ADMIN")
    void updateUser(User user);
 
    @Secured({ "ROLE_DBA", "ROLE_ADMIN" })
    void deleteUser();
    
}
复制代码

权限不足时,方法抛出Access Denied异常。@Secured注解会使用一个String数组作为参数。每个String值是一个权限,调用这个方法至少需要具备其中的一个权限。

2、@RolesAllowed

  • @DenyAll拒绝所有访问;
  • @RolesAllowed注解和@Secured注解在各个方面基本上都是一致的,@RolesAllowed({"ROLE_USER","ROLE_ADMIN"})该方法只要具有“ROLE_USER","ROLE_ADMIN"任意一种权限就可以访问;
  • @PermitAll允许所有访问;

3、SpEL注解

要开启表达式驱动的注解,只需要在Spring Security配置文件中添加如下注解:

@EnableGlobalMethodSecurity(prePostEnabled = true)

(1)、@PreAuthorize

该注解用于方法前验证权限,比如限制非VIP用户提交blog的note字段字数不得超过1000字:

@PreAuthorize("hasRole('ROLE_ADMIN') and #form.note.length() <= 1000 or hasRole('ROLE_VIP')")
public void writeBlog(Form form){
    ...
}

表达式中的#form部分直接引用了方法中的同名参数。这使得Spring Security能够检查传入方法的参数,并将这些参数用于认证决策的制定。

(2)、@PostAuthorize

方法后调用权限验证,比如校验方法返回值:

@PreAuthorize("hasRole(ROLE_USER)")
@PostAuthorize("returnObject.user.userName == principal.username")
public User getUserById(long id){
    ...        
}

Spring Security在SpEL中提供了名为returnObject 的变量。在这里方法返回一个User对象,所以这个表达式可以直接访问user对象中的userName属性。

二、权限控制案例

1、@PreAuthorize注解使用案例

接着上一节,要开启这些注解,只需要在Spring Security配置文件中添加如下注解:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
   ...  
}

在CustomUserDetailsService中,我们给当前登录用户授予了”admin”的权限,我们将这块代码改造一下:当登录用户为admin的时候,其拥有”admin”权限,其它用户则只有”test”权限:

复制代码
@Service
public class CustomUserDetailsService implements UserDetailsService {
    /**
     * 点击登录时会调用该函数、并传入登录名  根据用户名查询数据库获取用户信息
     * @param username:登录用户名
     * @return: 返回用户信息
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //模拟一个用户 替代数据库获取逻辑
        User user = new User();
        user.setUsername(username);
        user.setPassword("123456");
        // 输出加密后的密码
        System.out.println(user.getPassword());

        List<GrantedAuthority> authorities = new ArrayList<>();
        if (StringUtils.equalsIgnoreCase("admin", username)) {
            authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
        } else {
            authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("test");
        }

        return new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(),
                user.isEnabled(),
                user.isAccountNonExpired(),
                user.isCredentialsNonExpired(),
                user.isAccountNonLocked(),
                authorities);
    }
}
复制代码

在类TestController添加一个方法,并且使用权限注解标明只有拥有“admin”权限的人才能访问:

@GetMapping("/auth/admin")
@PreAuthorize("hasAuthority('admin')")
public String authenticationTest() {
    return "您拥有admin权限,可以查看";
}

启动系统,访问http://127.0.0.1:8080/index,使用admin账号登录:

访问http://127.0.0.1:8080/auth/admin

亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。

日期姓名金额
2023-09-06*源19
2023-09-11*朝科88
2023-09-21*号5
2023-09-16*真60
2023-10-26*通9.9
2023-11-04*慎0.66
2023-11-24*恩0.01
2023-12-30I*B1
2024-01-28*兴20
2024-02-01QYing20
2024-02-11*督6
2024-02-18一*x1
2024-02-20c*l18.88
2024-01-01*I5
2024-04-08*程150
2024-04-18*超20
2024-04-26.*V30
2024-05-08D*W5
2024-05-29*辉20
2024-05-30*雄10
2024-06-08*:10
2024-06-23小狮子666
2024-06-28*s6.66
2024-06-29*炼1
2024-06-30*!1
2024-07-08*方20
2024-07-18A*16.66
2024-07-31*北12
2024-08-13*基1
2024-08-23n*s2
2024-09-02*源50
2024-09-04*J2
2024-09-06*强8.8
2024-09-09*波1
2024-09-10*口1
2024-09-10*波1
2024-09-12*波10
2024-09-18*明1.68
2024-09-26B*h10
2024-09-3010
2024-10-02M*i1
2024-10-14*朋10
2024-10-22*海10
2024-10-23*南10
2024-10-26*节6.66
2024-10-27*o5
2024-10-28W*F6.66
2024-10-29R*n6.66
2024-11-02*球6
2024-11-021*鑫6.66
2024-11-25*沙5
2024-11-29C*n2.88
posted @   大奥特曼打小怪兽  阅读(1158)  评论(5编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
如果有任何技术小问题,欢迎大家交流沟通,共同进步

公告 & 打赏

>>

欢迎打赏支持我 ^_^

最新公告

程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)。

了解更多

点击右上角即可分享
微信分享提示