Spring Security是一个可以为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组能够在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减小了为企业系统安全控制编写大量重复代码的工做。java
spring security 3.0
已经能够使用spring el
表达式来控制受权,容许在表达式中使用复杂的布尔逻辑来控制访问的权限。git
Spring Security可用表达式对象的基类是SecurityExpressionRoot。github
表达式 | 描述 |
---|---|
hasRole([role] ) |
用户拥有制定的角色时返回true (Spring security 默认会带有ROLE_ 前缀),去除参考Remove the ROLE_ |
hasAnyRole([role1,role2]) |
用户拥有任意一个制定的角色时返回true |
hasAuthority([authority]) |
等同于hasRole ,但不会带有ROLE_ 前缀 |
hasAnyAuthority([auth1,auth2]) |
等同于hasAnyRole |
permitAll |
永远返回true |
denyAll |
永远返回false |
anonymous |
当前用户是anonymous 时返回true |
rememberMe |
当前勇士是rememberMe 用户返回true |
authentication |
当前登陆用户的authentication 对象 |
fullAuthenticated |
当前用户既不是anonymous 也不是rememberMe 用户时返回true |
hasIpAddress('192.168.1.0/24')) |
请求发送的IP匹配时返回true |
部分代码:spring
......
private String defaultRolePrefix = "ROLE_"; //ROLE_前缀
/** Allows "permitAll" expression */
public final boolean permitAll = true; //所有true
/** Allows "denyAll" expression */
public final boolean denyAll = false; //所有false
public final boolean permitAll() {
return true;
}
public final boolean denyAll() {
return false;
}
public final boolean isAnonymous() {
//是不是anonymous
return trustResolver.isAnonymous(authentication);
}
public final boolean isRememberMe() {
//是不是rememberme
return trustResolver.isRememberMe(authentication);
}
......
复制代码
onfig.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')")
.anyRequest().authenticated();
复制代码
这里咱们定义了应用/person/*
URL的范围,该URL只针对拥有ADMIN
或者USER
权限的用户有效。express
config.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')")
.antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)")
.anyRequest()
.access("@rbacService.hasPermission(request,authentication)");
复制代码
@Component("rbacService")
@Slf4j
public class RbacServiceImpl implements RbacService {
/** * uri匹配工具 */
private AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
log.info("【RbacServiceImpl】 --hasPermission={}", authentication.getPrincipal());
Object principal = authentication.getPrincipal();
boolean hasPermission = false;
//有多是匿名的anonymous
if (principal instanceof SysUser) {
//admin永远放回true
if (StringUtils.equals("admin", ((SysUser) principal).getUsername())) {
hasPermission = true;
} else {
//读取用户所拥有权限全部的URL 在这里所有返回true
Set<String> urls = new HashSet<>();
for (String url : urls) {
if (antPathMatcher.match(url, request.getRequestURI())) {
hasPermission = true;
break;
}
}
}
}
return hasPermission;
}
public boolean checkUserId(Authentication authentication, int id) {
return true;
}
}
复制代码
效果以下:编程
针对方法级别的访问控制比较复杂,Spring Security
提供了四种注解,分别是@PreAuthorize
, @PreFilter
, @PostAuthorize
和 @PostFilter
安全
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MerryyouSecurityConfig extends WebSecurityConfigurerAdapter {
复制代码
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
@ConditionalOnMissingBean(PasswordEncoder.class)
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
复制代码
/** * 查询全部人员 */
@PreAuthorize("hasRole('ADMIN')")
@ApiOperation(value = "得到person列表", notes = "")
@GetMapping(value = "/persons")
public List<Person> getPersons() {
return personService.findAll();
}
复制代码
@PreAuthorize 注解适合进入方法前的权限验证app
@PreAuthorize("hasRole('ADMIN')")
List<Person> findAll();
复制代码
@PostAuthorize 在方法执行后再进行权限验证,适合验证带有返回值的权限。Spring EL
提供 返回对象可以在表达式语言中获取返回的对象returnObject
。框架
@PostAuthorize("returnObject.name == authentication.name")
Person findOne(Integer id);
复制代码
//当有多个对象是使用filterTarget进行标注
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {
...
}
复制代码
@PreAuthorize("hasRole('ADMIN')")
@PostFilter("filterObject.name == authentication.name")
List<Person> findAll();
复制代码
效果以下:ide
从个人 github 中下载,github.com/longfeizhen…