shiro常用注解和过滤器,编写自定义注解实现 anon 所有人访问功能

1. 注解

在这里插入图片描述
已登录,未记住我,重开浏览器之后,就成了未登录

@RequiresGuest:未登录可以访问;认证过或使用记住我功能拒绝访问
@RequiresAuthentication: 认证过可以访问,其他时候拒绝访问
@RequiresUser: 认证过或使用记住我功能可以访问
@RequiresPermissions(value = {“user:create”, “user:update”}, logical = Logical.AND)
同时具备2个权限才能访问
@RequiresPermissions(value = {“user:create”, “user:update”}, logical = Logical.OR)
拥有其中任意一个权限就可以访问
@RequiresRoles 跟 @RequiresPermissions 使用差不多的

2. 过滤器

在这里插入图片描述

3. 自定义注解

一般做法:ShiroFilterFactoryBean 中设置 filterChainDefinitionMap 如图:
在这里插入图片描述
一旦接口发生了变更就得重新写一下接口路径,这很麻烦,于是编写自定义注解完成这个繁琐的操作

正片开始
思路:自定义注解@Anon 通过反射获取所有标记这个注解的接口,然后加入filterChainDefinitionMap

3.1 自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Anon {
}

3.2 JwtFilter中处理

public class JwtFilter extends BasicHttpAuthenticationFilter {

	/**
     * 执行登录认证
     *
     * 在ShiroConfig中获取全部的接口 会导致aop失效
     *    原因:controller 和 service 被提前实例化,导致这些类不会被 BeanPostProcessor 代理,从而导致部分 aop 功能失效
     *    分析:获取所有接口的目的在于判断这个接口是否标记了 Anon 注解,也就是是否能够机型匿名访问
     *         之前是提前获取接口添加到 filterChainDefinitionMap 从而实现匿名访问
     *         JwtFilter是认证的入口,并且所有请求都会到达这里,在这里进行判断就可以避免上述问题的发生
     *    解决:通过处理器适配器获取 handler 及目标类的目标方法,判断是否包含 Anon 注解
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        WebApplicationContext applicationContext = RequestContextUtils.findWebApplicationContext(httpServletRequest);
        RequestMappingHandlerMapping handlerMapping = applicationContext.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        HandlerExecutionChain handler = null;
        try {
            handler = handlerMapping.getHandler(httpServletRequest);
            Annotation[] declaredAnnotations = ((HandlerMethod) handler.getHandler()).
                    getMethod().getDeclaredAnnotations();
            for(Annotation annotation:declaredAnnotations){
                if(Anon.class.equals(annotation.annotationType())){
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        executeLogin(request, response);
        return true;
    }
}

好的,针对您的问题,您可以使用Shiro提供的权限注解 `@RequiresPermissions`,并通过自定义注解实现权限控制。 以下是一个示例代码,其实现了一个自定义注解 `@ApiPermission`,并在 `ShiroFilterFactoryBean` 中添加了该注解,用于控制开放接口的访问权限: ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ApiPermission { String[] value() default {}; } public class ApiPermissionFilter extends AuthorizationFilter { @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { Subject subject = getSubject(request, response); String[] permissions = (String[]) mappedValue; if (permissions == null || permissions.length == 0) { return true; } for (String permission : permissions) { if (subject.isPermitted(permission)) { return true; } } return false; } } @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); factoryBean.setSecurityManager(securityManager); Map<String, Filter> filterMap = new LinkedHashMap<>(); filterMap.put("apiPermission", new ApiPermissionFilter()); factoryBean.setFilters(filterMap); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/api/**", "apiPermission[api:read]"); filterChainDefinitionMap.put("/**", "authc"); factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return factoryBean; } } @RestController public class ApiController { @GetMapping("/api/test") @ApiPermission("api:read") public String test() { return "Hello, World!"; } } ``` 在上述代码中,我们定义了一个 `ApiPermissionFilter`,用于判断用户是否具有访问开放接口的权限。然后,在 `ShiroFilterFactoryBean` 中添加了该过滤器,并在 `filterChainDefinitionMap` 中使用 `apiPermission[api:read]` 来控制 `/api/**` 下的所有请求的访问权限。 最后,在 `ApiController` 中使用 `@ApiPermission("api:read")` 注解来标识需要具有 `api:read` 权限才能访问的接口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值