Spring Security 实现权限控制功能(8)

导读:本篇文章讲解 Spring Security 实现权限控制功能(8),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1. 权限注解

Spring Security权限控制可以配合授权注解使用。

Spring Security提供了三种不同的安全注解:

  • Spring Security自带的@Secured注解;

  • JSR-250的@RolesAllowed注解;

  • 表达式驱动的注解,包括@PreAuthorize、@PostAuthorize、@PreFilter和 @PostFilter。

1.1 @Secured

在Spring-Security.xml中启用@Secured注解:

<global-method-security secured-annotations="enabled"/>

例如只有拥有权限“ROLE_ADMIN”的用户才能访问下面这个方法:

@Secured("ROLE_ADMIN")
public void test(){
    ...
}

权限不足时,方法抛出Access Denied异常。

@Secured注解会使用一个String数组作为参数。每个String值是一个权限,调用这个方法至少需要具备其中的一个权限。如:

@Secured({"ROLE_ADMIN","ROLE_USER"})
public void test(){
    ...
}

1.2 @RolesAllowed

@RolesAllowed注解和@Secured注解在各个方面基本上都是一致的。启用@RolesAllowed注解:

<global-method-security jsr250-annotations="enabled"/>

使用如下:

@RolesAllowed("ROLE_ADMIN")
public void test(){
    ...
}

1.3 SpEL注解

启用该注解:

<global-method-security pre-post-annotations="enabled"/>

1.3.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能够检查传入方法的参数,并将这些参数用于认证决策的制定。

1.3.2 @PostAuthorize

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

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

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

2. 权限控制

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

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

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

@Configuration
public class UserDetailService implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 模拟一个用户,替代数据库获取逻辑
        MyUser user = new MyUser();
        user.setUserName(username);
        user.setPassword(this.passwordEncoder.encode("123456"));
        // 输出加密后的密码
        System.out.println(user.getPassword());

        List<GrantedAuthority> authorities = new ArrayList<>();
        if (StringUtils.equalsIgnoreCase("cc", username)) {
            authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
        } else {
            authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("test");
        }
        return new User(username, user.getPassword(), user.isEnabled(),
                user.isAccountNonExpired(), user.isCredentialsNonExpired(),
                user.isAccountNonLocked(), authorities);
    }
}

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

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

启动系统,使用cc账号登录:

image-20220426165739320

image-20220426165758005

可看到,cc可以访问该资源。

使用aa账号登录:

image-20220426165918623

image-20220426165936641

可以看到,aa没有权限访问,返回403错误码。

我们可以自定义权限不足处理器来处理权限不足时候的操作。

新增一个处理器MyAuthenticationAccessDeniedHandler,实现AccessDeniedHandler接口:

@Component
public class MyAuthenticationAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("很抱歉,您没有该访问权限");
    }
}

然后将这个处理器添加到Spring Security配置链中:

// 处理权限不足
@Autowired
private MyAuthenticationAccessDeniedHandler authenticationAccessDeniedHandler;

 @Override
protected void configure(HttpSecurity http) throws Exception {
    http.exceptionHandling()
            .accessDeniedHandler(authenticationAccessDeniedHandler)
        .and()
    ......
}

重启系统,再次使用aa账号访问/auth/admin

image-20220426170314166

3. 项目地址

权限控制

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

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/16705.html

(0)
小半的头像小半

相关推荐

极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!