

学习 Shiro(二):REST API Filter
source link: http://muziyuchen.com/shiro-2/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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,关键步骤如下:
- 请求目标 Servlet,Servlet Container 检测到存在两个 Filter 并创建了 FilterChain;
- 执行 FilterChain 中第一个 Filter 的
doFilter()
方法; - 第一个 Filter 完成处理,调用 FilterChain 的
doFilter()
方法,从而执行 Filter Chain 中第二个 Filter 的doFilter()
方法; - 第二个 Filter 完成处理,调用 FilterChain 的
doFilter()
方法,从而执行 Servlet 的service()
方法; - Servlet 完成,第二个 Filter 调用 FilterChain 的
doFilter()
方法返回; - 第二个 Filter 完成,第一个 Filter 调用 FilterChain 的
doFilter()
方法返回; - 第一个 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.UserFilterREST 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
参考
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK