学习 Shiro(二):REST API Filter

Shiro Web 的设计目标仍是解决单体 Web 服务的安全问题,如配置 authc.loginUrl 登录页面,用户被禁止访问则重定向到登录页面。

显然,authc 过滤器的默认行为显然并不适合提供 REST API 的 Web 服务。

Shiro 简单易扩展,可以对 Shiro Web 进行定制化,从而更好支持 REST API。

目标如下所示:

  • 未登录,返回 HTTP 401 Unauthorized
  • 未授权,返回 HTTP 403 Forbidden

Filter

Shiro Web 使用了 Filter 对 HTTP 请求和响应进行过滤。 javax.servlet.Filter 接口定义如下:

public interface Filter {

    public void init(FilterConfig filterConfig) throws ServletException;

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;

    public void destroy();

}

在 Shiro Web 中 Filter 的实现是 org.apache.shiro.web.servlet.ShiroFilter 类。在 Shiro Spring 中 Filter 的实现是 org.apache.shiro.spring.web.SpringShiroFilter 类。

如果定义了两个 Filter,关键步骤如下:

  1. 请求目标 Servlet,Servlet Container 检测到存在两个 Filter 并创建了 FilterChain;
  2. 执行 FilterChain 中第一个 Filter 的 doFilter() 方法;
  3. 第一个 Filter 完成处理,调用 FilterChain 的 doFilter() 方法,从而执行 Filter Chain 中第二个 Filter 的 doFilter() 方法;
  4. 第二个 Filter 完成处理,调用 FilterChain 的 doFilter() 方法,从而执行 Servlet 的 service() 方法;
  5. Servlet 完成,第二个 Filter 调用 FilterChain 的 doFilter() 方法返回;
  6. 第二个 Filter 完成,第一个 Filter 调用 FilterChain 的 doFilter() 方法返回;
  7. 第一个 Filter 完成。

学习 Shiro(二):REST API Filter

在 Shiro Web 中,路径规则:

/user/** = authc
/** = anon

会转化为一个 FilterChain,而 authc 和 anon 就是 Shiro Web 默认提供的 Filter 实现。

默认 Filter 表格:

名称 实现类
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter

REST API Filter

Spring Boot 集成 org.apache.shiro:shiro-spring-boot-web-starter 为例,演示如何自定义 Filter。

public class RestApiFilter extends FormAuthenticationFilter { // ①

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        Subject subject = getSubject(request, response); 

        if (subject.isAuthenticated()) { // ②
            HttpServletResponse httpResponse = WebUtils.toHttp(response);
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        } else { // ③
            HttpServletResponse httpResponse = WebUtils.toHttp(response);
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
        }

        return false;
    }

}

① 修改 authc 在访问禁止的行为,选择继承 org.apache.shiro.web.filter.authc.FormAuthenticationFilter 并覆盖其 onAccessDenied() 方法;

② 如果没有认证,返回 HTTP 401 Unauthorized;

③ 如果没有鉴权,返回 HTTP 403 Forbidden。

添加自定义 Filter:

@Configuration
public class ShiroWebFilterConfiguration extends AbstractShiroWebFilterConfiguration {

    @Bean
    @Override
    protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean bean = super.shiroFilterFactoryBean();

        bean.getFilters().put("api", new RestApiFilter());

        return bean;
    }

}

使用自定义 Filter:

/api/** = api

参考

  • Apache Shiro Web Support – Apache Shiro

原文 

http://muziyuchen.com/shiro-2/

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 学习 Shiro(二):REST API Filter

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址