spring security 3.0
已經能夠使用spring el
表達式來控制受權,容許在表達式中使用複雜的布爾邏輯來控制訪問的權限。java
Spring Security可用表達式對象的基類是SecurityExpressionRoot。git
表達式 | 描述 |
---|---|
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 |
部分代碼:github
...... 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
權限的用戶有效。spring
config.antMatchers("/person/*").access("hasRole('ADMIN') or hasRole('USER')") .antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)") .anyRequest() .access("@rbacService.hasPermission(request,authentication)");
RbacServiceImplexpress
@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
app
@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 getPersons() { return personService.findAll(); }
PreAuthorizeide
@PreAuthorize 註解適合進入方法前的權限驗證工具
@PreAuthorize("hasRole('ADMIN')") List<Person> findAll();
PostAuthorizeui
@PostAuthorize 在方法執行後再進行權限驗證,適合驗證帶有返回值的權限。Spring EL
提供 返回對象可以在表達式語言中獲取返回的對象return Object
。
@PostAuthorize("returnObject.name == authentication.name") Person findOne(Integer id);
PreFilter 針對參數進行過濾
//當有多個對象是使用filterTarget進行標註 @PreFilter(filterTarget="ids", value="filterObject%2==0") public void delete(List<Integer> ids, List<String> usernames) { ... }
PostFilter 針對返回結果進行過濾
@PreAuthorize("hasRole('ADMIN')") @PostFilter("filterObject.name == authentication.name") List<Person> findAll();
效果以下: