Apache Shiro配置unauthorizedUrl不生效,如何实现无权限时跳转至access-denied.jsf页面?
解决Shiro权限不足时无法跳转至自定义拒绝页面的问题
我看你遇到的核心问题是:虽然权限控制逻辑生效,但无权限时没有跳转到你配置的/common/access-denied.jsf,反而显示空白。这是因为你用了动态角色/权限,而原来的[roles]块是针对静态角色映射的配置,对动态授权场景不生效。下面是具体的解决步骤:
1. 显式配置perms过滤器的未授权跳转地址
Shiro中,perms对应的过滤器是PermissionsAuthorizationFilter,你需要在shiro-web.ini里显式定义这个过滤器,并设置它的unauthorizedUrl属性,而不是依赖静态的[roles]配置。修改你的ini文件如下:
# Using default form based security filter org.apache.shiro.web.filter.authc.FormAuthenticationFilter authc = org.apache.shiro.web.filter.authc.FormAuthenticationFilter authc.loginUrl = /common/login.jsf authc.successUrl = /portal/dashboard.jsf # 新增:定义perms过滤器并设置未授权跳转地址 perms = org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter perms.unauthorizedUrl = /common/access-denied.jsf # 原[roles]块仅适用于静态角色映射,动态授权场景下无效,可注释/删除 # [roles] # roles.unauthorizedUrl = /common/access-denied.jsf # Protected URLs [urls] # 新增:确保拒绝页面允许匿名访问,避免跳转后触发登录循环 /common/access-denied.jsf = anon /portal/customerEdit** = authc, perms["customer:create"] /WEB-INF/layout/portal/** = authc /portal/** = authc /admin/** = authc
2. 关键原理解释
- 静态的
[roles]块仅适用于硬编码的角色-权限映射(比如admin = user:create,user:delete这种固定配置),而你用的是从数据库动态获取权限的方式,所以这个配置不会被触发。 - 当使用
perms过滤器做权限校验时,它自身的unauthorizedUrl属性才是控制权限不足时跳转的核心,必须显式配置才能生效。
3. 额外检查事项
- 确认
/common/access-denied.jsf页面没有被Shiro的authc等过滤器保护,否则用户无权限跳转后会被要求登录,形成循环。 - 如果你自定义了
PermissionsAuthorizationFilter,要确保没有重写onAccessDenied方法时忽略跳转逻辑,若需重写可手动处理跳转:@Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException { if (!isLoginRequest(request, response)) { // 跳转到自定义拒绝页面 WebUtils.issueRedirect(request, response, getUnauthorizedUrl()); return false; } return super.onAccessDenied(request, response); }
这样修改后,当用户没有customer:create权限访问portal/customerEdit.jsf时,就会自动跳转到你配置的拒绝页面了。
内容的提问来源于stack exchange,提问作者vished2000




