Spring Security 4 使用@PreAuthorize,@PostAuthorize, @Secured, EL实现方法安全

原文地址: http://blog.csdn.net/w605283073/article/details/51327182
本文探讨Spring Security 4 基于@PreAuthorize, @PostAuthorize, @Secured和 Spring EL表达式的方法级的安全。

想要开启Spring方法级安全,你需要在已经添加了@Configuration注解的类上再添加@EnableGlobalMethodSecurity注解:

package com.websystique.springsecurity.configuration;  

import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;  
import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  

@Configuration  
@EnableWebSecurity  
@EnableGlobalMethodSecurity(prePostEnabled = true)  
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {  


    @Autowired  
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {  
        auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");  
        auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");  
        auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");  
    }  

    @Override  
    protected void configure(HttpSecurity http) throws Exception {  

      http.authorizeRequests()  
        .antMatchers("/", "/home").access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")  
        .and().formLogin().loginPage("/login")  
        .usernameParameter("ssoId").passwordParameter("password")  
        .and().exceptionHandling().accessDeniedPage("/Access_Denied");  
    }  
}  

@EnableGlobalMethodSecurity 开启Spring Security 全局方法安全,等价的XML配置如下:

[html] view plain copy 在CODE上查看代码片派生到我的代码片

package com.websystique.springsecurity.service;  

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();  

}  

在上面的例子中,updateUser 方法只能被拥有ADMIN 权限的用户调用。deleteUser 方法只能够被拥有DBA 或者ADMIN 权限的用户调用。

如果有不具有声明的权限的用户调用此方法,将抛出AccessDenied异常。

如果你想指定AND(和)这个条件,我的意思说deleteUser 方法只能被同时拥有ADMIN & DBA 。但是仅仅通过使用 @Secured注解是无法实现的。

但是你可以使用Spring的新的注解@PreAuthorize/@PostAuthorize(支持Spring EL),使得实现上面的功能成为可能,而且无限制。

@PreAuthorize / @PostAuthorize
Spring的 @PreAuthorize/@PostAuthorize 注解更适合方法级的安全,也支持Spring 表达式语言,提供了基于表达式的访问控制。

@PreAuthorize 注解适合进入方法前的权限验证, @PreAuthorize可以将登录用户的roles/permissions参数传到方法中。

@PostAuthorize 注解使用并不多,在方法执行后再进行权限验证。

所以它适合验证带有返回值的权限。Spring EL 提供 返回对象能够在表达式语言中获取返回的对象returnObject。

请参考 Common Built-In Expressions 获取支持的表达式.

现在言归正常,使用@PreAuthorize / @PostAuthorize注解

package com.websystique.springsecurity.service;  

import org.springframework.security.access.prepost.PostAuthorize;  
import org.springframework.security.access.prepost.PreAuthorize;  

import com.websystique.springsecurity.model.User;  


public interface UserService {  

    List<User> findAllUsers();  

    @PostAuthorize ("returnObject.type == authentication.name")  
    User findById(int id);  

    @PreAuthorize("hasRole('ADMIN')")  
    void updateUser(User user);  

    @PreAuthorize("hasRole('ADMIN') AND hasRole('DBA')")  
    void deleteUser(int id);  

}  

由于 @PreAuthorize可以使用Spring 表达式语言, 使用EL表达式可以轻易的表示任意条件. deleteUser方法 可以被拥有ADMIN & DBA角色的用户调用 .

另外,我们增加了带有@PostAuthorize注解的findById()方法。通过@PostAuthorize注解 method(User object)的返回值在Spring表达式语言中可以通过returnObject 来使用。在例子中我们确保登录用户只能获取他自己的用户对象。

上面就是@Secured, @PreAuthorize, @PostAuthorize 和EL的使用

展开阅读全文

没有更多推荐了,返回首页