shiro与springMVC整合
2016-06-03 18:20
525 查看
注:该文基于springMVC已经配置好。
![](http://img.blog.csdn.net/20160603174218178)
shiro所需jar包:
![](http://img.blog.csdn.net/20160603174652626)
在web.xml里添加shiroFilter:该过滤器名字将与spring.xml里注入的过滤器名字一致。所以当有请求时进了web.xml里时,请求就会被该过滤器转到spring.xml里的shiro过滤器。
securityManager:安全管理器。是必须注入的,所有的过滤都被它管理着。
loginUrl:没有登录时就会跳转到它指定的地址,如果不指定该属性,则会自动去找项目的根目录下的”/login.jsp”页面。
unauthorizedUrl:没有权限时默认的跳转路径。
filterChainDefinitions:过滤链。它可对路径进行过滤。如:
/refuse.jsp = anon anon过滤器表示认证不通过也可访问,所以这句代码表示refuse.jsp路径在没有登录时也可访问
/login.do = authc authc过滤器表示需要认证通过才可访问,也就是说login.do在没有登录时,是不能访问的,除非设为了loginUrl的值。
使用注解的方式赋的权限,首先看看controller里通过注解限定的权限:
当没有权限访问时,就会跳转到refuse.jsp页面,但是注解方式配置无权限跳转需要在springMVC的配置文件(springMVC-servlet.xml)里配,可能是因为shiro注解赋权限的配置在这里面吧。代码如下:
1. 架构预览
项目结构:shiro所需jar包:
2. 整合shiro
2.1 配置web.xml
注意,由于shiro的主要作用就是拦截判断,所以我们不再需要springMVC的LoginInterceptor和
PermissionInterceptor拦截器了。其余的springMVC配置的代码保持不变。
在web.xml里添加shiroFilter:该过滤器名字将与spring.xml里注入的过滤器名字一致。所以当有请求时进了web.xml里时,请求就会被该过滤器转到spring.xml里的shiro过滤器。
<!-- shiro过虑器,DelegatingFilterProxy通过代理模式将spring容器中的bean和filter关联起来 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <!-- 设置true由servlet容器控制filter的生命周期 --> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> <!-- 设置spring容器filter的bean id,如果不设置则找与filter-name一致的bean--> <init-param> <param-name>targetBeanName</param-name> <param-value>shiroFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2.2 配置spring.xml
(本人将shiro的配置直接配在该文件下的,一般会新建一个shiro自己的配置文件,就像springMVC的springMVC-servlet.xml文件一样)<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/login"/><!-- 如果不写的话,默认去找login.jsp页面 --> <property name="unauthorizedUrl" value="/index.jsp"/> <!-- 认证不通过访问的页面 --> <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 --> <property name="filterChainDefinitions"> <value> /refuse.jsp = anon /login.do = authc <!-- anon过滤器表示没有权限也可访问login.do --> /logout.do = logout <!-- 表示访问logout.do时就直接访问logout这个过滤器,即直接退出 --> /** = authc <!-- 表示其他的所有路径都要通过认证后才能访问 --> </value> </property> </bean> <!-- 注入自定义realm --> <bean id="myShiroRealm" class="com.mvc.realm.MyShiroRealm"> <property name="accountService" ref="accountService" /> </bean> <!-- 安全管理器 :必须注入--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myShiroRealm"></property> </bean> <!-- 注入查询用户名与密码的service实现类 --> <bean id="accountService" class="com.mvc.service.impl.AccountService"></bean>
securityManager:安全管理器。是必须注入的,所有的过滤都被它管理着。
loginUrl:没有登录时就会跳转到它指定的地址,如果不指定该属性,则会自动去找项目的根目录下的”/login.jsp”页面。
unauthorizedUrl:没有权限时默认的跳转路径。
filterChainDefinitions:过滤链。它可对路径进行过滤。如:
/refuse.jsp = anon anon过滤器表示认证不通过也可访问,所以这句代码表示refuse.jsp路径在没有登录时也可访问
/login.do = authc authc过滤器表示需要认证通过才可访问,也就是说login.do在没有登录时,是不能访问的,除非设为了loginUrl的值。
2.3 默认拦截器
过滤器简称 | 类名 | 解释 | 示例 |
---|---|---|---|
1.认证过滤器 | |||
anon | org.apache.shiro.web.filter.authc.AnonymousFilter | 可匿名访问。无参,一般用于过滤静态资源 | /admins/**=anon 表示admins下的所有路径皆可匿名访问` |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | 认证登录后才可访问。 | /admins/user/**=authc |
authc属性 | usernameParam:表单提交的用户名参数名( username); passwordParam:表单提交的密码参数名(password); rememberMeParam:表单提交的密码参数名(rememberMe); | loginUrl:登录页面地址(/login.jsp);successUrl:登录成功后的默认重定向地址; | failureKeyAttribute:登录失败后错误信息存储key(shiroLoginFailure); |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter | http身分认证器。无参 | /admins/user/**=authcBasic |
authcBasic属性 | applicationName:弹出登录框显示的信息(application); | ||
user | org.apache.shiro.web.filter.authc.UserFilter | 表示必须存在用户 | /admins/user/**=user 表示身份认证通过或通过记住我认证通过的可以访问,此时进行登录操作不会做检查 |
logout | org.apache.shiro.web.filter.authc.LogoutFilter | 退出拦截器 | /logout.do=logout |
主要属性 | redirectUrl:退出成功后重定向的地址(/) | ||
2.授权过滤器 | |||
perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter | 权限授权过滤器。有参,多参时写成拼接字符串,各参之间以逗号分隔。多参时需每个权限都通过时才算通过,相当于hasAllRoles() | 单参:/admins/user/**=perms[add]表示该路径只有add权限时才可访问。多参: /admins/user/**=perms["add,delete"] |
port | org.apache.shiro.web.filter.authz.PortFilter | 端口过滤器 | /admins/user/**=port[8080] 当端口号不是8080时会将访问url的端口改为8080后再跳转。 |
主要属性 | port(80):指定可以通过的端口; | ||
roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter | 角色授权过滤器,可多参 | |
属性 | loginUrl:登录页面地址;unauthorizedUrl: 未授权后重定向的地址; | admins/user/**=roles[“admin,guest”] 多参时,都通过才算通过 | |
rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter | 请求方法拦截器(GET=read,POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read, MKCOL=create),它自动根据请求方法构建权限字符串。/admins/user/**=perms[user:post]会拼接“user:create”权限字符串 | /users=rest[user],会自动拼出“user:read,user:create,user:update,user:delete”权限字符串进行权限匹配(所有都得匹配,isPermittedAll); |
ssl | org.apache.shiro.web.filter.authz.SslFilter | 安全协议拦截器,只有请求协议是https才能通过;否则自动跳转会https端口(443);其他和port拦截器一样; | /admins/user/**=ssl |
2.4 自定义realm
此realm先不从数据库查询权限数据/**** * 自定义Realm * * @author Peter * */ public class MyShiroRealm extends AuthorizingRealm { @Override public String getName() { return"customRealm"; } // 支持什么类型的token @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; } /*** * 获取授权信息 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) { //先自定义一个query权限,就不从数据库查询了 String username = (String) pc.fromRealm(getName()).iterator().next(); if (username != null) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission("query");//权限 return info; } return null; } /*** * 获取认证信息 * * 问题:如何在登录后不再进登录页面了呢??????????????????????????? */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken at) { UsernamePasswordToken token = (UsernamePasswordToken) at; // 通过表单接收的用户名 // String username = token.getUsername(); String username = (String) at.getPrincipal(); if (username != null && !"".equals(username)) { User user = accountService.getUserByUserName(username); if (user != null && user.getPassword().equals(new String(token.getPassword())) && user.getUsername().equals(token.getUsername())) { return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName()); }else{ //throw new UnknownAccountException(); //如果用户名错误 throw new IncorrectCredentialsException(); //如果密码错误 } } return null; } /**用户的业务类**/ private IAccountService accountService; public IAccountService getAccountService() { return accountService; } public void setAccountService(IAccountService accountService) { this.accountService = accountService; } }
2.5 登录
/*** * 提交数据的登录 */ @RequestMapping(value = "login.do") public String login(String username, String password,ModelMap model) { Subject subject = SecurityUtils.getSubject(); if(subject.isAuthenticated()){ return "home.jsp"; }else{ UsernamePasswordToken token = new UsernamePasswordToken(username, password); String error = null; try { subject.login(token); // subject.logout(); } catch (UnknownAccountException e) { error = "用户名/密 错误"; } catch (IncorrectCredentialsException e) { error = "用/密码 错误"; } catch (AuthenticationException e) { //其他错误,比如锁定,如果想单独处理请单独catch处理 error = "其他错误:" + e.getMessage(); } model.addAttribute("msg", error); System.out.println("用户认证状态:"+subject.isAuthenticated()); if(subject.isAuthenticated()){ return "redirect:home"; }else{ return "/login.jsp"; } } }
2.6 退出
由于shiro的sessionManager管理session,所以不用开发退出功能,直接使用shiro的logout拦截器即可退出。
<!-- 请求logout.do执行退出操作 --> /logout.do= logout
2.7 无权限访问跳转到refuse.jsp
当用户无操作权限,shiro将跳转到refuse.jsp页面。使用注解的方式赋的权限,首先看看controller里通过注解限定的权限:
/** * 查询:注解query权限:只有当realm里查回的权限里有query时才可访问该方法 * * 即访问该方法时,会先拿query权限去realm里查看授权时查回的权限里是否有query权限 * 有的话则允许访问,否则不允许 * @return * @author Peter */ @RequestMapping(value = "query") @RequiresPermissions("query")//指定访问的权限 public String query(){ System.out.println("查询内容"); return "/home.jsp"; }
当没有权限访问时,就会跳转到refuse.jsp页面,但是注解方式配置无权限跳转需要在springMVC的配置文件(springMVC-servlet.xml)里配,可能是因为shiro注解赋权限的配置在这里面吧。代码如下:
<!-- 使用shiro注解赋权限 --> <bean class=" org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <!-- 捕获到没有权限异常跳转 到拒绝访问页--> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- 如果配置了视图解析,则可不用写jsp这个后缀 --> <prop key="org.apache.shiro.authz.UnauthorizedException">/refuse</prop> </props> </property> </bean>
相关文章推荐
- Apache Shiro 使用手册(一) Shiro架构介绍
- Apache Shiro 使用手册(二) Shiro 认证
- Apache Shiro 使用手册(五) Shiro 配置说明
- Apache Shiro 使用手册(四) Realm 实现
- 详解Spring Boot 集成Shiro和CAS
- 让Apache Shiro保护你的应用
- 基于Spring框架的Shiro配置方法
- spring boot 1.5.4 集成shiro+cas,实现单点登录和权限控制
- 使用Shiro实现登录成功后跳转到之前的页面
- Shiro 控制并发登录人数限制及登录踢出的实现代码
- 搭建分布式架构5--ZooKeeper 集群的安装 3ff0
- Spring+mybatis+shiro+freemarker+ehcache+ldap+mongo
- 第四章 INI配置
- 第五章 编码/加密
- 第六章 Realm及相关对象
- Shiro预览
- JFinal-Beetl-Shiro(JdbcRealm)-例子
- springrain技术详解
- Apache Shiro 使用手册
- 基于Spring框架的Shiro配置