原文地址: http://blog.csdn.net/w605283073/article/details/51327182 本文探討SPRing Security 4 基于@PreAuthorize, @PostAuthorize, @Secured和 Spring EL表達式的方法級的安全。
想要開啟Spring方法級安全,你需要在已經(jīng)添加了@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 權(quán)限的用戶調(diào)用。deleteUser 方法只能夠被擁有DBA 或者ADMIN 權(quán)限的用戶調(diào)用。
如果有不具有聲明的權(quán)限的用戶調(diào)用此方法,將拋出AccessDenied異常。
如果你想指定AND(和)這個條件,我的意思說deleteUser 方法只能被同時擁有ADMIN & DBA 。但是僅僅通過使用 @Secured注解是無法實現(xiàn)的。
但是你可以使用Spring的新的注解@PreAuthorize/@PostAuthorize(支持Spring EL),使得實現(xiàn)上面的功能成為可能,而且無限制。
@PreAuthorize / @PostAuthorize Spring的 @PreAuthorize/@PostAuthorize 注解更適合方法級的安全,也支持Spring 表達式語言,提供了基于表達式的訪問控制。
@PreAuthorize 注解適合進入方法前的權(quán)限驗證, @PreAuthorize可以將登錄用戶的roles/permissions參數(shù)傳到方法中。
@PostAuthorize 注解使用并不多,在方法執(zhí)行后再進行權(quán)限驗證。
所以它適合驗證帶有返回值的權(quán)限。Spring EL 提供 返回對象能夠在表達式語言中獲取返回的對象returnObject。
請參考 Common Built-In Expressions 獲取支持的表達式.
現(xiàn)在言歸正常,使用@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角色的用戶調(diào)用 .
另外,我們增加了帶有@PostAuthorize注解的findById()方法。通過@PostAuthorize注解 method(User object)的返回值在Spring表達式語言中可以通過returnObject 來使用。在例子中我們確保登錄用戶只能獲取他自己的用戶對象。
上面就是@Secured, @PreAuthorize, @PostAuthorize 和EL的使用
新聞熱點
疑難解答