shiro与spring整合在web项目中的应用
2018-01-24 12:40
627 查看
一、思想认识
这里shiro就相当于一个拦截器,这个拦截器与spring整合在了一起,当一个URL请求的时候首先--->走shiro拦截器------>springMVC的handler函数;
二、shiro与spring项目的整合
1、shiro在web.xml中的配置
在web系统中,shiro也通过filter进行拦截。filter拦截后将操作权交给spring中配置的filterChain(过虑链儿)shiro提供很多filter。
在applicationContext-shiro.xml
中配置web.xml中fitler对应spring容器中的bean。
在web.xml中配置filter
2、配置applicationContext-shiro.xml
上面就是把shiro与spring的整合,与项目融合一起;
3、shiro的过虑器
anon:例子/admins/**=anon 没有参数,表示可以匿名使用。
authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,FormAuthenticationFilter是表单认证,没有参数
perms:例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
user:例如/admins/user/**=user没有参数表示必须存在用户,身份认证通过或通过记住我认证通过的可以访问,当登入操作时不做检查
Jsp页面添加:
<%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %>
<shiro:principal property="username"/> 显示用户身份中的属性值
修改itemsList.jsp页面:
接下来就是针对在一个项目中使用shiro对用户进行 认证和授权
三、shiro在web开发中的应用
1、登录认证
涉及到JSP页面传参到request域中到shiro拦截器中,然后拿着传进来的参数与realm域中的数据库主题参数进行对比的一个过程;
2、shiro缓存
针对授权频繁查询数据库,需要使用shiro缓存;
hiro中提供了对认证信息和授权信息的缓存。shiro默认是关闭认证信息缓存的,对于授权信息的缓存shiro默认开启的。主要研究授权信息缓存,因为授权的数据量大。
用户认证通过。
该 用户第一次授权:调用realm查询数据库
该 用户第二次授权:不调用realm查询数据库,直接从缓存中取出授权信息(权限标识符)。
之后把给缓存配置在shiro的安全管理器中;
如果用户非正常退出,缓存自动清空。
如果修改了用户的权限,而用户不退出系统,修改的权限无法立即生效。
需要手动进行编程实现:
在权限修改后调用realm的clearCache方法清除缓存。
下边的代码正常开发时要放在service中调用。
在service中,权限修改后调用realm的方法。
会话数据。
在shiro的安全管理器中配置shiro的session管理
e5ae
户主题的数据和与realm中的用户主题的数据对比之前;
shiro使用FormAuthenticationFilter进行表单认证,验证校验的功能应该加在FormAuthenticationFilter中,在认证之前进行验证码校验。
需要写FormAuthenticationFilter的子类,继承FormAuthenticationFilter,改写它的认证方法,在认证之前进行验证码校验。
在applicationContext-shiro.xml中配置自定义的拦截器
通过shiro的拦截器验证后进入到springMVC的handler函数login.action
6、记住我的配置
这个功能一般是在登录的页面,勾选出自动登录或者是记住用户名密码之后,下次登录时不用再输入用户名和密码;
也即是:用户登陆选择“自动登陆”本次登陆成功会向cookie写身份信息,下次登陆从cookie中取出身份信息实现自动登陆。
6.1、要求:
向cookie记录身份信息需要用户身份信息对象实现序列化接口,如下
在shiro的安全管理器中配置 记住我的功能;
注意:这个记住我的JSP页面传的参数与shiro的配置文件中的rememberMe
要一致,这个直接走shiro进行cookie保存在了,浏览器中;
项目信息源码:点击打开链接
这里shiro就相当于一个拦截器,这个拦截器与spring整合在了一起,当一个URL请求的时候首先--->走shiro拦截器------>springMVC的handler函数;
二、shiro与spring项目的整合
1、shiro在web.xml中的配置
在web系统中,shiro也通过filter进行拦截。filter拦截后将操作权交给spring中配置的filterChain(过虑链儿)shiro提供很多filter。
在applicationContext-shiro.xml
中配置web.xml中fitler对应spring容器中的bean。
在web.xml中配置filter
<!-- shiro的filter --> <!-- 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、配置applicationContext-shiro.xml
<!-- web.xml中shiro的filter对应的bean --> <!-- Shiro 的Web过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 --> <property name="loginUrl" value="/login.action" /> <!-- 认证成功统一跳转到first.action,建议不配置,shiro认证成功自动到上一个请求路径 --> <property name="successUrl" value="/first.action"/> <!-- 通过unauthorizedUrl指定没有权限操作时跳转页面--> <property name="unauthorizedUrl" value="/refuse.jsp" /> <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 --> <property name="filterChainDefinitions"> <value> <!-- 对静态资源设置匿名访问 --> /images/** = anon /js/** = anon /styles/** = anon /** = authc <!-- /** = anon所有url都可以匿名访问 --> </value> </property> </bean> <!-- securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm" /> </bean> <!-- realm --> <bean id="customRealm" class="cn.itcast.ssm.shiro.CustomRealm"> </bean> </beans>
上面就是把shiro与spring的整合,与项目融合一起;
3、shiro的过虑器
过滤器简称 | 对应的java类 |
anon | org.apache.shiro.web.filter.authc.AnonymousFilter |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter |
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 |
logout | org.apache.shiro.web.filter.authc.LogoutFilter |
authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,FormAuthenticationFilter是表单认证,没有参数
perms:例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
user:例如/admins/user/**=user没有参数表示必须存在用户,身份认证通过或通过记住我认证通过的可以访问,当登入操作时不做检查
4、jsp标签 授权
Jsp页面添加:
<%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %>
标签名称 | 标签条件(均是显示标签内容) |
<shiro:authenticated> | 登录之后 |
<shiro:notAuthenticated> | 不在登录状态时 |
<shiro:guest> | 用户在没有RememberMe时 |
<shiro:user> | 用户在RememberMe时 |
<shiro:hasAnyRoles name="abc,123" > | 在有abc或者123角色时 |
<shiro:hasRole name="abc"> | 拥有角色abc |
<shiro:lacksRole name="abc"> | 没有角色abc |
<shiro:hasPermission name="abc"> | 拥有权限资源abc |
<shiro:lacksPermission name="abc"> | 没有abc权限资源 |
<shiro:principal> | 显示用户身份名称 |
修改itemsList.jsp页面:
接下来就是针对在一个项目中使用shiro对用户进行 认证和授权
三、shiro在web开发中的应用
1、登录认证
涉及到JSP页面传参到request域中到shiro拦截器中,然后拿着传进来的参数与realm域中的数据库主题参数进行对比的一个过程;
2、shiro缓存
针对授权频繁查询数据库,需要使用shiro缓存;
hiro中提供了对认证信息和授权信息的缓存。shiro默认是关闭认证信息缓存的,对于授权信息的缓存shiro默认开启的。主要研究授权信息缓存,因为授权的数据量大。
用户认证通过。
该 用户第一次授权:调用realm查询数据库
该 用户第二次授权:不调用realm查询数据库,直接从缓存中取出授权信息(权限标识符)。
通常使用ehcache来与shiro进行整合;
1.1.1.1 配置cacheManager
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!--diskStore:缓存数据持久化的目录 地址 --> <diskStore path="F:\develop\ehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
之后把给缓存配置在shiro的安全管理器中;
<!-- securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm" /> <!-- 注入缓存管理器 --> <property name="cacheManager" ref="cacheManager"/> </bean>
<!-- 缓存管理器 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/> </bean>
3、 缓存清空
如果用户正常退出,缓存自动清空。如果用户非正常退出,缓存自动清空。
如果修改了用户的权限,而用户不退出系统,修改的权限无法立即生效。
需要手动进行编程实现:
在权限修改后调用realm的clearCache方法清除缓存。
下边的代码正常开发时要放在service中调用。
在service中,权限修改后调用realm的方法。
在realm中定义clearCached方法: //清除缓存 public void clearCached() { PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals(); super.clearCache(principals); }
4、 sessionManager
和shiro整合后,使用shiro的session管理,shiro提供sessionDao操作会话数据。
在shiro的安全管理器中配置shiro的session管理
<!-- securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm" /> <!-- 注入缓存管理器 --> <property name="cacheManager" ref="cacheManager"/> <!-- 注入session管理器 --> <property name="sessionManager" ref="sessionManager" /> </bean>
<!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session的失效时长,单位毫秒 --> <property name="globalSessionTimeout" value="600000"/> <!-- 删除失效的session --> <property name="deleteInvalidSessions" value="true"/> </bean>
5、 验证码
1.1.1 思路
注意的是:验证码是在JSP页面的输入数据与实际生成的放在http的session中的进行对比的,发生在用e5ae
户主题的数据和与realm中的用户主题的数据对比之前;
shiro使用FormAuthenticationFilter进行表单认证,验证校验的功能应该加在FormAuthenticationFilter中,在认证之前进行验证码校验。
需要写FormAuthenticationFilter的子类,继承FormAuthenticationFilter,改写它的认证方法,在认证之前进行验证码校验。
自定义FormAuthenticationFilter
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter { //原FormAuthenticationFilter的认证方法 @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { //在这里进行验证码的校验 //从session获取正确验证码 HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpSession session =httpServletRequest.getSession(); //取出session的验证码(正确的验证码) String validateCode = (String) session.getAttribute("validateCode"); //取出页面的验证码 //输入的验证和session中的验证进行对比 String randomcode = httpServletRequest.getParameter("randomcode"); if(randomcode!=null && validateCode!=null && !randomcode.equals(validateCode)){ //如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中 httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError"); //拒绝访问,不再校验账号和密码 return true; } return super.onAccessDenied(request, response); } }
在applicationContext-shiro.xml中配置自定义的拦截器
<!-- 自定义filter配置 --> <property name="filters"> <map> <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中--> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property>
<!-- 自定义form认证过虑器 --> <!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 --> <bean id="formAuthenticationFilter" class="cn.itcast.ssm.shiro.CustomFormAuthenticationFilter "> <!-- 表单中账号的input名称 --> <property name="usernameParam" value="username" /> <!-- 表单中密码的input名称 --> <property name="passwordParam" value="password" /> <!-- 记住我input的名称 --> <property name="rememberMeParam" value="rememberMe"/> </bean>
通过shiro的拦截器验证后进入到springMVC的handler函数login.action
@Controller public class LoginController { @Autowired private SysService sysService; //用户登陆提交方法 /** * * <p>Title: login</p> * <p>Description: </p> * @param session * @param randomcode 输入的验证码 * @param usercode 用户账号 * @param password 用户密码 * @return * @throws Exception */ /*@RequestMapping("/login") public String login(HttpSession session, String randomcode,String usercode,String password)throws Exception{ //校验验证码,防止恶性攻击 //从session获取正确验证码 String validateCode = (String) session.getAttribute("validateCode"); //输入的验证和session中的验证进行对比 if(!randomcode.equals(validateCode)){ //抛出异常 throw new CustomException("验证码输入错误"); } //调用service校验用户账号和密码的正确性 ActiveUser activeUser = sysService.authenticat(usercode, password); //如果service校验通过,将用户身份记录到session session.setAttribute("activeUser", activeUser); //重定向到商品查询页面 return "redirect:/first.action"; }*/ //登陆提交地址,和applicationContext-shiro.xml中配置的loginurl一致 @RequestMapping("login") public String login(HttpServletRequest request)throws Exception{ //shiro在认证过程中,如果出现认证错误,将异常类路径通过request返回 //如果登陆失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名 String exceptionClassName = (String) request.getAttribute("shiroLoginFailure"); //根据shiro返回的异常类路径判断,抛出指定异常信息 if(exceptionClassName!=null){ if (UnknownAccountException.class.getName().equals(exceptionClassName)) { //最终会抛给异常处理器 throw new CustomException("账号不存在"); } else if (IncorrectCredentialsException.class.getName().equals( exceptionClassName)) { throw new CustomException("用户名/密码错误"); } else if("randomCodeError".equals(exceptionClassName)){ throw new CustomException("验证码错误 "); }else { throw new Exception();//最终在异常处理器生成未知错误 } } //此方法不处理登陆成功(认证成功),shiro认证成功会自动跳转到上一个请求路径 //登陆失败还到login页面 return "login"; } /* //用户退出 @RequestMapping("/logout") public String logout(HttpSession session)throws Exception{ //session失效 session.invalidate(); //重定向到商品查询页面 return "redirect:/first.action"; }*/ }
6、记住我的配置
这个功能一般是在登录的页面,勾选出自动登录或者是记住用户名密码之后,下次登录时不用再输入用户名和密码;
也即是:用户登陆选择“自动登陆”本次登陆成功会向cookie写身份信息,下次登陆从cookie中取出身份信息实现自动登陆。
6.1、要求:
向cookie记录身份信息需要用户身份信息对象实现序列化接口,如下
public class ActiveUser implements java.io.Serializable{}}
在shiro的安全管理器中配置 记住我的功能;
<!-- securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm" /> <!-- 注入缓存管理器 --> <property name="cacheManager" ref="cacheManager"/> <!-- 注入session管理器 --> <property name="sessionManager" ref="sessionManager" /> <!-- 记住我 --> <property name="rememberMeManager" ref="rememberMeManager"/> </bean>
<!-- rememberMeManager管理器,写cookie,取出cookie生成用户信息 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="rememberMeCookie" /> </bean> <!-- 记住我cookie --> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <!-- rememberMe是cookie的名字 --> <constructor-arg value="rememberMe" /> <!-- 记住我cookie生效时间30天 --> <property name="maxAge" value="2592000" /> </bean>
注意:这个记住我的JSP页面传的参数与shiro的配置文件中的rememberMe
<!-- rememberMe是cookie的名字 --> <constructor-arg value="rememberMe" />
要一致,这个直接走shiro进行cookie保存在了,浏览器中;
项目信息源码:点击打开链接
相关文章推荐
- 010-shiro与spring web项目整合【四】缓存Ehcache
- 008-shiro与spring web项目整合【二】认证、授权、session管理
- shiro与spring web项目整合
- 009-shiro与spring web项目整合【三】验证码、记住我
- 007-shiro与spring web项目整合【一】基础搭建
- JAVAWEB开发之权限管理(三)——shiro与企业项目整合开发(基于Spring)
- shiro学习:shiro整合springweb项目实现用户登录和退出
- 在 Web 项目中应用 Apache Shiro 开源权限框架
- web项目中spring如何整合RabbitMQ?
- web项目中spring如何整合RabbitMQ?
- spring和hibernate整合开发web项目的创建及所需的jar包的添加
- Java Web项目整合spring和Hibernate时报错!
- Spring boot项目整合thymeleaf和shiro
- JAVA_WEB项目之如何解决Struts2和Spring整合时出现中文数据提交时出现乱码
- Spring整合Web项目原理
- 使用spring-loaded开源项目,实现java程序和web应用的热部署
- Spring整合Web项目原理-理解不了,忽略
- Spring 整合web项目原理
- Axis2在Web项目中整合Spring
- WEB项目整合spring-data-hbase出现NoSuchMethodError: PageContextImpl.evaluateExpression