您的位置:首页 > 编程语言 > Java开发

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

2017-02-19 18:17 483 查看
原文地址: 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的使用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring security