SpringSecurity开启注解权限(5)

x33g5p2x  于2021-08-23 转载在 Java  
字(4.9k)|赞(0)|评价(0)|浏览(461)

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')

相关文章