1.@EnableGlobalMethodSecurity 注解介紹
Spring Security默認是在配置類中使用URL進行攔截,禁用使用注解,想要開啟注解使用則需要在配置類上加上 如下注解@EnableGlobalMethodSecurity;
注解源碼如下,共支持 prePostEnabled, securedEnabled,jsr250Enabled,proxyTargetClass 四種參數;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({GlobalMethodSecuritySelector.class})
@EnableGlobalAuthentication
@Configuration
public @interface EnableGlobalMethodSecurity {
boolean prePostEnabled() default false;
boolean securedEnabled() default false;
boolean jsr250Enabled() default false;
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
在Spring Security 2.0 開始 支持 JSR-250 注釋 以及框架的原始@Secured注釋;
2.@Secured注解使用方式
需要在配置類加上 @EnableGlobalMethodSecurity(securedEnabled = true) 表明使用 @Secured 注解;
配置示例如下
/**
* @Author lsc
* <p> </p>
*/
@EnableWebSecurity// 開啟springSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//.....略
}
注解使用示例如下,該注解只能使用在方法上面
@GetMapping("test/seu")
@Secured("ROLE_USER")
public String testSecurity() {
return "需要USER權限";
}
測試結果如下

@Secured 源碼如下
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Secured {
String[] value();
}
該注解可以使用多個角色進行控制
@Secured({"ROLE_USER","ROLE_ADMIN"})
3.JSR-250注解
JSR-250 注釋 使用需要在配置類上加上 @EnableGlobalMethodSecurity(jsr250Enabled = true) ; 配置示例如下:
@EnableWebSecurity// 開啟springSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//.....略
}
- @RolesAllowed 允許的角色;
- @PermitAll 允許任何人訪問
- @DenyAll 拒絕任何人訪問
使用方式如下;
@RolesAllowed({"USER","ADMIN"}) 表示 只有 USER, ADMIN 角色權限才可以訪問;
@GetMapping("test/allow")
@RolesAllowed({"USER","ADMIN"})
public String testAllow() {
return "需要權限";
}
@GetMapping("test/perm")
@PermitAll
public String testPerm() {
return "允許";
}
@GetMapping("test/deny")
@DenyAll
public String testDeny() {
return "拒絕";
}
4.prePostEnabled 規范
prePostEnabled 沒有 原生的spring注解功能強大,所以其使用需要借助spring的EL表達式;
需要在配置類上加上 @EnableGlobalMethodSecurity(prePostEnabled = true) 注解
配置示例
@EnableWebSecurity// 開啟springSecurity
//@EnableGlobalMethodSecurity(securedEnabled = true)
//@EnableGlobalMethodSecurity(jsr250Enabled = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//.....略
}
主要注解如下
- @PreAuthorize --方法之前驗證授權
- @PostAuthorize --授權方法之后被執行
- @PostFilter --在方法執行之后執行,用於過濾集合;
- @PreFilter --在方法執行之前執行,用於過濾集合;
注解使用方式
@GetMapping("api/admin")
@PreAuthorize("hasRole('ADMIN')")
public String authAdmin() {
return "需要ADMIN權限";
}
@GetMapping("api/test")
@PreAuthorize("isAnonymous()")
public String authUser() {
return "匿名用戶訪問";
}
以及 hasAuthority 使用方式如下
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
使用EL表達式判定方式如下
@GetMapping("api/has")
@PreAuthorize("#sysUser.username == 'admin' ")
public String hasPerm(SysUser sysUser) {
return "EL測試";
}
還可以使用 @P 注解獲取參數
@GetMapping("api/sys")
@PreAuthorize("#c.username == authentication.principal ")
public String hasPerm2(@P("c")SysUser sysUser) {
return "EL測試";
}
如果是Spring Data的@Param注解
@PreAuthorize("#n == authentication.principal")
public String hasPerm2(@Param("n")SysUser sysUser) {
return "EL測試";
}
5 權限被拒絕處理器
如果當用戶訪問自身不具有的權限接口時,springSecurity 會將異常信息傳遞給 AccessDeniedHandler ;我們只需要實現它即可;示例如下
/**
* @author lsc
* <p> 權限不足處理 </p>
*/
@Component
public class DenyHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
// 設置響應頭
httpServletResponse.setContentType("application/json;charset=utf-8");
// 返回值
ResultPage result = ResultPage.error(CodeMsg.PERM_ERROR);
httpServletResponse.getWriter().write(JSON.toJSONString(result));
}
}
6 常見內置表達式
| 表達 | 描述 |
|---|---|
hasRole([role]) |
如果當前主體具有指定角色,則返回true。默認情況下,如果提供的角色不以“ROLE_”開頭,則會添加該角色。這可以通過修改DefaultWebSecurityExpressionHandler上的defaultRolePrefix來自定義。 |
hasAnyRole([role1,role2]) |
如果當前主體具有任何提供的角色(以逗號分隔的字符串列表給出),則返回true。默認情況下,如果提供的角色不以“ROLE_”開頭,則會添加該角色。這可以通過修改DefaultWebSecurityExpressionHandler上的defaultRolePrefix來自定義。 |
hasAuthority([authority]) |
如果當前主體具有指定的權限,則返回true。 |
hasAnyAuthority([authority1,authority2]) |
如果當前主體具有任何提供的權限(以逗號分隔的字符串列表給出),則返回true |
principal |
允許直接訪問代表當前用戶的主體對象 |
authentication |
允許直接訪問從SecurityContext獲取的當前Authentication對象 |
permitAll |
始終評估為true |
denyAll |
始終評估為false |
isAnonymous() |
如果當前主體是匿名用戶,則返回true |
isRememberMe() |
如果當前主體是remember-me用戶,則返回true |
isAuthenticated() |
如果用戶不是匿名用戶,則返回true |
isFullyAuthenticated() |
如果用戶不是匿名用戶或記住我用戶,則返回true |
hasPermission(Object target, Object permission) |
如果用戶有權訪問給定權限的提供目標,則返回true。例如,hasPermission(domainObject, 'read') |
hasPermission(Object targetId, String targetType, Object permission) |
如果用戶有權訪問給定權限的提供目標,則返回true。例如,hasPermission(1, 'com.example.domain.Message', 'read') |
本套教程
- springSecurity入門(1)
- springSecurity配置(2)
- springSecurity登陸與退出json形式交互(3)
- springSecurity前后端分離集成jwt(4)
- SpringSecurity開啟注解權限(4)
- springSecurity Cors 處理(6)
- 待續或者已更新
源碼地址: 關注公眾號知識追尋者,后台回復:springSecurity 獲取
