Shiro的认证与授权过程的401自定义信息返回格式

发布时间:2023年12月22日

spring boot与shiro整合的很多这个不用多赘述,主要分享下过滤器这块

shiro中的部分过滤器

anon过滤器:用于处理匿名访问,即不需要身份验证的URL。
authc过滤器:用于进行身份验证,如果身份验证失败,将会返回一个HTTP 401 Unauthorized响应。
authcBasic过滤器:用于进行HTTP基本身份验证,如果身份验证失败,将会返回一个HTTP 401 Unauthorized响应。
authcBearer过滤器:用于进行OAuth2授权,如果授权失败,将会返回一个HTTP 401 Unauthorized响应。
perms过滤器:用于检查用户是否具有指定权限,如果用户没有指定权限,将会返回一个HTTP 403 Forbidden响应。
port过滤器:用于检查请求的端口是否与配置文件中指定的端口匹配,如果不匹配,将会返回一个HTTP 403 Forbidden响应。
rest过滤器:用于处理RESTful请求,例如GET、POST、PUT、DELETE等。
ssl过滤器:用于检查请求是否使用安全连接,如果不使用安全连接,将会返回一个HTTP 403 Forbidden响应。
user过滤器:用于检查用户是否已经登录,如果用户未登录,将会返回一个HTTP 401 Unauthorized响应

上述过滤器各自对应了一个具体的实现类,需要的找对应的过滤器

anon->AnonymousFilter
authc->FormAuthenticationFilter
authcBasic->BasicHttpAuthenticationFilter
roles->RolesAuthorizationFilter

正常流程会在ShiroConfig中配置下部分代码

	@Bean
    public CustomHttpAuthenticationFilter customHttpAuthenticationFilter(){
        return new CustomHttpAuthenticationFilter();
    }
    @Bean
    public CustomRolesAuthenticationFilter customRolesAuthenticationFilter(){
        return new CustomRolesAuthenticationFilter();
    }
    
	@Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login","anon");
        filterChainDefinitionMap.put("/unauthc","anon");
        filterChainDefinitionMap.put("/test/test1","anon");
        filterChainDefinitionMap.put("/test/test2","authcBasic");
        filterChainDefinitionMap.put("/test/test3","authcBasic,roles[r002]");
//        filterChainDefinitionMap.put("/**","authcBasic");
        Map<String, Filter> filterMap = new HashMap<>();
        

// 此处,将自定义重写的过滤器添加到过滤器集合中,目前看来对这个过滤器匹配时通过过滤器名称比较的,所有authcBasic/role这些名称一定要写对,不然可能匹配不上
        filterMap.put("authcBasic",customHttpAuthenticationFilter());
        filterMap.put("roles", customRolesAuthenticationFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

filterChainDefinitionMap.put(“/test/test3”,“authcBasic,roles[r002]”);
此种请求会加经过customHttpAuthenticationFilter(继承自BasicHttpAuthenticationFilter)进行认证和customRolesAuthenticationFilter(继承自RolesAuthorizationFilter) 进行授权校验,默认返回信息格式:

{
    "timestamp": "2023-12-22T02:13:59.375+00:00",
    "status": 401,
    "error": "Unauthorized",
    "path": "/test/test3"
}

认证不通过会返回401,Unauthorized,需要在customHttpAuthenticationFilter中进行处理,

public class CustomHttpAuthenticationFilter extends BasicHttpAuthenticationFilter {
    //  sendChallenge重写的目的是避免前端在没有登录的情况下访问@RequiresPermissions()等未授权接口返回401错误,
    //  给前端调用接口一个数据,让前端去重新登陆
    //  如果使用浏览器访问,浏览器会弹出一个输入账号密码的弹框,重写后浏览器访问出现接口数据

    @Override
    protected boolean sendChallenge(ServletRequest request, ServletResponse response) {
        System.err.println("Authentication required: sending 401 Authentication challenge response.");
        // 工具类把第二个参数转为json字符串写到response中
        HttpUtils.returnJson((HttpServletResponse) response, Result.Custom(HttpStatus.SC_UNAUTHORIZED,"未授权"));
        return false;
    }
}

授权不通过会返回403,Forbidden,需要在customRolesAuthenticationFilter进行处理

public class CustomRolesAuthenticationFilter extends RolesAuthorizationFilter {
    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        Subject subject = getSubject(request, response);
        String[] rolesArray = (String[]) mappedValue;

        if (rolesArray == null || rolesArray.length == 0) {
            //no roles specified, so nothing to check - allow access.
            return true;
        }

        Set<String> roles = CollectionUtils.asSet(rolesArray);
        boolean hasAllRoles = subject.hasAllRoles(roles);
        if (!hasAllRoles){
            HttpUtils.returnJson((HttpServletResponse) response, Result.ERROR("当前用户不具备该角色"));
        }
        return hasAllRoles;
    }
}

通过以上处理可将默认的401异常信息进行格式化成符合自定义格式反馈到前端

Shiro是基于过滤器实现的,有问题最好是多查查过滤器,以及过滤器的匹配规则,确定自己代码走到那一个过滤器才好进一步处理,
在这里插入图片描述

文章来源:https://blog.csdn.net/pepper5/article/details/135136003
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。