本系列博文目录:http://www.javashuo.com/article/p-ewndobct-kn.htmljava
ShiroFilter拦截器是整个Shiro的入口,用于拦截须要安全控制的请求并进行处理。ajax
shiro封装了不少不一样用途的拦截器,这里只介绍几个比较经常使用的拦截器,更详细介绍能够参考博文spring
《第八章 拦截器机制——跟我学Shiro》:http://jinnianshilongnian.iteye.com/blog/2025656安全
因为此拦截器常常须要继承并重写里面的方法,来扩展本身的登陆拦截规则,因此会进行详细介绍。app
等录拦截器主要有两个做用框架
一、拦截登陆表单提交的路径(在拦截器工厂中配置)。jsp
建立登陆认证所须要的Token令牌,并进入登陆认证流程。ide
二、拦截要求登陆才能够访问的路径时(在拦截规则中配置)。url
若是已经登陆则直接进入到要访问路径,若是未登陆则访问被拒绝并跳转到登陆页。spa
方法介绍
createToken():
此方法用于建立登陆认证令牌,令牌内存储了登陆认证时所需的数据。当咱们须要扩展shiro原有令牌的时候会重写此方法,将扩展的令牌字段存入令牌。最典型的例子就是在令牌中增长了验证码字段。(令牌会在其余章节另做介绍)
/** * 建立Token */ @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { String username = getUsername(request);//获取用户名 表单name:username String password = getPassword(request);//获取密码 表单name:password boolean rememberMe = isRememberMe(request);//获取是否记住我 表单name:rememberMe String captchaId = WebUtils.getCleanParam(request, "captchaId");//获取验证码id String captcha = WebUtils.getCleanParam(request, "captcha");//获取用户输入的验证码字符 return new CaptchaAuthenticationToken(username, password,captchaId, captcha, rememberMe);//存入本身定义的包含验证码的Token }
onLoginSuccess():
登陆认证成功后的行为。此方法只有在进行登陆认证成功后访问一次。以后再访问页面时不会调用此方法。
onAccessDenied():
访问被拒绝后的行为。在拦截规则中指定须要登录后才能访问的路径,若是没有登陆则认为访问被拒绝。
此方法处理访问被拒绝后的逻辑,最多见的就是对于ajax访问拒绝的特殊处理。
此方法处理完成后,默认行为会跳转到登陆页(能够在拦截器工厂中配置 或 setLoginUrl方法设置登录页)。
这里要注意若是是登陆操做,拦截器会先拦截并断定为拒绝访问进入到此方法,而后再去进行建立Token和登陆认证等操做。
setLoginUrl():
设置登录页路径。默认/login.jsp,能够在拦截器工厂中配置 或 使用此方法重置。
访问被拒绝时咱们可使用此方法返回到其余登录页面,而不是以前的登陆页。
@Override protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { setLoginUrl("/otherlLogin"); return super.onAccessDenied(servletRequest, servletResponse); }
getUsername():
得到登录用户名。表单name值必须是username。
getPassword():
得到登录密码。表单name值必须是password。
isRememberMe():
得到是否记住我。表单name值必须是rememberMe。
这个类用于spring框架中配置过滤器。
经过此工厂类能够很方便的配置拦截器的各类基本属性。
方法:
setSecurityManager:
必输。注入一个SecurityManager类,SecurityManager负责管理整个shiro核心验证功能。
setLoginUrl:
配置登陆页路径。这是一个很是方便的用法,咱们不须要在拦截器中来定义他。
这里须要注意登陆页即便不配置拦截规则也必定会被authc拦截。
在这有一个事情比较坑,setLoginUrl所配置的路径便是页面的访问路径,同时又是登录表单提交的路径。页面访问使用的是GET方式提交,表单使用的是POST方式提交。
/** * LoginController中的内容 */ //根路径 @RequestMapping(value = "/", method = RequestMethod.GET) public String loginForm() { return "redirect:login"; } //登陆页面 @RequestMapping(value = "/login", method = RequestMethod.GET) public String loginInput(@ModelAttribute("message") String message) { //判断是否已经登陆 或 是否已经记住我 if (SecurityUtils.getSubject().isAuthenticated() || SecurityUtils.getSubject().isRemembered()) { return "redirect:/home"; } else { return "login"; } } //登陆表单提交 @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(HttpServletRequest request, RedirectAttributes redirectAttributes) { //登陆认证逻辑 }
在这里说明一下若是不一致致使的现象
若是只配了页面的访问路径则,登陆时将不会触发shiro登陆拦截器。
若是只配了登录表单提交的路径则,拦截器判断为未登陆时将没法回到登陆页面。
setSuccessUrl:
配置登陆成功页路径。这是一个很是方便的用法,咱们不须要在拦截器中来定义他。
setUnauthorizedUrl:
配置没有权限跳转的页面。这是一个很是方便的用法,咱们不须要在拦截器中来定义他。
setFilterChainDefinitionMap:
设置拦截规则。拦截规则是经过一个Map进行导入的。
拦截规则写法详见“拦截规则”部分。
setFilters:
用于注入本身实现的拦截器类。自定义拦截器通常是继承了shiro原有拦截器并重写了部分方法。
一个spring boot配置文件中拦截器工厂类的例子:
/** * 得到拦截器工厂类 */ @Bean (name = "authenticationFilter") public AuthenticationFilter authenticationFilter() { return new AuthenticationFilter(); } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager,AuthenticationFilter authenticationFilter) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager);//设置SecurityManager,必输 shiroFilterFactoryBean.setLoginUrl("/login");//配置登陆路径(登陆页的路径和表单提交的路径必须是同一个,页面的GET方式,表单的POST方式) shiroFilterFactoryBean.setSuccessUrl("/home");//配置登陆成功页路径 shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");//配置没有权限跳转的页面 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put("/", "anon"); //无需登陆认证和受权就可访问的路径使用anon拦截器 filterChainDefinitionMap.put("/home/**", "user");//须要登陆认证的路径使用authc或user拦截器 filterChainDefinitionMap.put("/user/**", "user,perms[user-jurisdiction]");//须要权限受权的路径使用perms拦截器 filterChainDefinitionMap.put("/admin/**", "user,perms[admin-jurisdiction]");//authc和perms拦截器可同时使用 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//设置拦截规则 Map<String, Filter> map = new HashMap<String, Filter>(); map.put("authc", authenticationFilter);//自定义拦截器覆盖了FormAuthenticationFilter登陆拦截器所用的拦截器名authc shiroFilterFactoryBean.setFilters(map);//添加自定义拦截器 return shiroFilterFactoryBean; }
拦截规则使用Map<String, String>将路径与拦截器的映射关系进行匹配。
形式如:
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put("<拦截路径>", "<拦截器名称>");
<拦截器路径>
拦截器路径是一个从根路径开始的url,并支持通配符。
登陆页即便不配置也必定会被authc拦截。
<拦截器名称>
是shiro内置拦截器的名称,也能够本身实现拦截器为其定义名称。
anon - 无需登陆认证和受权就可访问的路径使用anon拦截器
authc - 须要登陆认证的路径使用authc拦截器
user - 用户拦截器,用户已经登陆认证 或 已经记住我 的均可以经过。
(user拦截器会自动调用authc 拦截器,因此若是要使用记住我功能只配置user便可)
perms[role_name] - 须要权限验证的路径使用perms拦截器。中括号内为权限名称列表。
多个拦截器能够混合使用用逗号分隔
例子:
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put("/", "anon"); //无需登陆认证和受权就可访问的路径使用anon拦截器 filterChainDefinitionMap.put("/home/**", "user");//须要登陆认证的路径使用authc或user拦截器 filterChainDefinitionMap.put("/user/**", "user,perms[user-jurisdiction]");//须要权限受权的路径使用perms拦截器 filterChainDefinitionMap.put("/admin/**", "user,perms[admin-jurisdiction]");//authc和perms拦截器可同时使用 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//设置拦截规则