shiro + mybatis+ spring (只用shiro的密码校验和并发剔除)——不用权限之类

http://blog.csdn.net/changliangwl/article/details/51455833

shiro + mybatis+ spring (只用shiro的密码校验和并发剔除)——不用权限之类

标签: shirojavamybatisspring

2016-05-20 09:13 103人阅读 评论(0) 收藏 举报

分类:

shiro(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。

[java] view plain copy

  1. </pre>          shiro 很强大,但往往项目不可能大改造,往往只需要部分功能,比如用到验证码,加密,还有就是同一个账户在两个地方登录,剔除第一个登录者,本文只提供思路和部 分代码,<p></p><p></p><p>自定义实现ream,< /p><p></p><pre name="code" class="java">package com.shiro.shiro.realm;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. import org.apache.shiro.authc.*;
  5. import org.apache.shiro.authz.AuthorizationInfo;
  6. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  7. import org.apache.shiro.realm.AuthorizingRealm;
  8. import org.apache.shiro.subject.PrincipalCollection;
  9. import org.apache.shiro.util.ByteSource;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import com.shiro.model.User;
  12. import com.shiro.service.UserService;
  13. public class UserRealm extends AuthorizingRealm {
  14. @Autowired
  15. private UserService userService;
  16. //获取授权信息
  17. @Override
  18. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  19. SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
  20. <span style="font-size:18px;">   <span style="color:#ff0000;"><strong>Set<String>  set =new HashSet<String>();
  21. set.add("*:*:*");</strong></span>
  22. <span style="color:#ff0000;"><strong>authorizationInfo.setRoles(set);
  23. authorizationInfo.setStringPermissions(set);
  24. return authorizationInfo;</strong></span></span>
  25. }
  26. //获取身份验证信息
  27. @Override
  28. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  29. String username = (String)token.getPrincipal();
  30. User user = userService.findByUsername(username);
  31. if(user == null) {
  32. throw new UnknownAccountException();//没找到帐号
  33. }
  34. if(Boolean.TRUE.equals(user.getLocked())) {
  35. throw new LockedAccountException(); //帐号锁定
  36. }
  37. //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
  38. SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
  39. user.getUsername(), //用户名
  40. user.getPassword(), //密码
  41. ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
  42. getName()  //realm name
  43. );
  44. return authenticationInfo;
  45. }
  46. @Override
  47. public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
  48. super.clearCachedAuthorizationInfo(principals);
  49. }
  50. @Override
  51. public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
  52. super.clearCachedAuthenticationInfo(principals);
  53. }
  54. @Override
  55. public void clearCache(PrincipalCollection principals) {
  56. super.clearCache(principals);
  57. }
  58. public void clearAllCachedAuthorizationInfo() {
  59. getAuthorizationCache().clear();
  60. }
  61. public void clearAllCachedAuthenticationInfo() {
  62. getAuthenticationCache().clear();
  63. }
  64. public void clearAllCache() {
  65. clearAllCachedAuthenticationInfo();
  66. clearAllCachedAuthorizationInfo();
  67. }
  68. }

[java] view plain copy

  1. 只要在<pre name="code" class="java">doGetAuthorizationInfo方法体里授权所有资源所有角色就好了

[java] view plain copy

  1. </pre><pre name="code" class="java">

[java] view plain copy

  1. 剔除功能

[java] view plain copy

  1. </pre><pre name="code" class="java"><pre name="code" class="java">package com.shiro.shiro.filter;
  2. import org.apache.shiro.cache.Cache;
  3. import org.apache.shiro.cache.CacheManager;
  4. import org.apache.shiro.session.Session;
  5. import org.apache.shiro.session.mgt.DefaultSessionKey;
  6. import org.apache.shiro.session.mgt.SessionManager;
  7. import org.apache.shiro.subject.Subject;
  8. import org.apache.shiro.web.filter.AccessControlFilter;
  9. import org.apache.shiro.web.util.WebUtils;
  10. import javax.servlet.ServletRequest;
  11. import javax.servlet.ServletResponse;
  12. import java.io.Serializable;
  13. import java.util.Deque;
  14. import java.util.LinkedList;
  15. /**
  16. * 并发剔除
  17. */
  18. public class KickoutSessionControlFilter extends AccessControlFilter {
  19. private String kickoutUrl; //踢出后到的地址
  20. private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
  21. private int maxSession = 1; //同一个帐号最大会话数 默认1
  22. private SessionManager sessionManager;
  23. private Cache<String, Deque<Serializable>> cache;
  24. public void setKickoutUrl(String kickoutUrl) {
  25. this.kickoutUrl = kickoutUrl;
  26. }
  27. public void setKickoutAfter(boolean kickoutAfter) {
  28. this.kickoutAfter = kickoutAfter;
  29. }
  30. public void setMaxSession(int maxSession) {
  31. this.maxSession = maxSession;
  32. }
  33. public void setSessionManager(SessionManager sessionManager) {
  34. this.sessionManager = sessionManager;
  35. }
  36. public void setCacheManager(CacheManager cacheManager) {
  37. this.cache = cacheManager.getCache("shiro-kickout-session");
  38. }
  39. @Override
  40. protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
  41. return false;
  42. }
  43. @Override
  44. protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
  45. Subject subject = getSubject(request, response);
  46. if(!subject.isAuthenticated() && !subject.isRemembered()) {//未授权且非remember
  47. //如果没有登录,直接进行之后的流程
  48. return true;
  49. }
  50. Session session = subject.getSession();
  51. String username = (String) subject.getPrincipal();
  52. Serializable sessionId = session.getId();
  53. //TODO 同步控制
  54. Deque<Serializable> deque = cache.get(username);
  55. if(deque == null) {
  56. deque = new LinkedList<Serializable>();
  57. cache.put(username, deque);
  58. }
  59. //如果队列里没有此sessionId,且用户没有被踢出;放入队列
  60. if(!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
  61. deque.push(sessionId);
  62. }
  63. //如果队列里的sessionId数超出最大会话数,开始踢人
  64. while(deque.size() > maxSession) {
  65. Serializable kickoutSessionId = null;
  66. if(kickoutAfter) { //如果踢出后者
  67. kickoutSessionId = deque.removeFirst();
  68. } else { //否则踢出前者
  69. kickoutSessionId = deque.removeLast();
  70. }
  71. try {
  72. Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
  73. if(kickoutSession != null) {
  74. //设置会话的kickout属性表示踢出了
  75. kickoutSession.setAttribute("kickout", true);
  76. }
  77. } catch (Exception e) {//ignore exception
  78. }
  79. }
  80. //如果被踢出了,直接退出,重定向到踢出后的地址
  81. if (session.getAttribute("kickout") != null) {
  82. //会话被踢出了
  83. try {
  84. subject.logout();//这里走的shiro的退出
  85. } catch (Exception e) { //ignore
  86. }
  87. saveRequest(request);
  88. WebUtils.issueRedirect(request, response, kickoutUrl);
  89. return false;
  90. }
  91. return true;
  92. }
  93. }

此处用到了缓存,当然可以自己实现,把session存到数据库中然后判断操作

[java] view plain copy

  1. </pre><pre name="code" class="java">再看下部分配置文件

[java] view plain copy

  1. </pre><pre name="code" class="java">

[java] view plain copy

  1. <pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:util="http://www.springframework.org/schema/util"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
  9. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
  10. <!-- 缓存管理器 -->
  11. <bean id="cacheManager" class="com.shiro.spring.cache.SpringCacheManagerWrapper">
  12. <property name="cacheManager" ref="springCacheManager"/>
  13. </bean>
  14. <!-- 凭证匹配器 -->
  15. <bean id="credentialsMatcher" class="com.shiro.shiro.credentials.CredentialsMatcher">
  16. <property name="hashAlgorithmName" value="md5"/>
  17. <property name="hashIterations" value="2"/>
  18. <property name="storedCredentialsHexEncoded" value="true"/>
  19. </bean>
  20. <!-- Realm实现 -->
  21. <bean id="userRealm" class="com.shiro.shiro.realm.UserRealm">
  22. <property name="credentialsMatcher" ref="credentialsMatcher"/>
  23. <property name="cachingEnabled" value="false"/>
  24. </bean>
  25. <!-- 会话ID生成器 -->
  26. <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
  27. <!-- 会话Cookie模板 maxAge=-1表示浏览器关闭时失效此Cookie-->
  28. <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
  29. <constructor-arg value="sid"/>
  30. <property name="httpOnly" value="true"/>
  31. <property name="maxAge" value="-1"/>
  32. </bean>
  33. <!-- 会话DAO -->
  34. <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
  35. <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
  36. <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
  37. </bean>
  38. <!-- 会话验证调度器 -->
  39. <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
  40. <property name="sessionValidationInterval" value="1800000"/>
  41. <property name="sessionManager" ref="sessionManager"/>
  42. </bean>
  43. <!-- 会话管理器 -->
  44. <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
  45. <property name="globalSessionTimeout" value="1800000"/>
  46. <property name="deleteInvalidSessions" value="true"/>
  47. <property name="sessionValidationSchedulerEnabled" value="true"/>
  48. <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
  49. <property name="sessionDAO" ref="sessionDAO"/>
  50. <property name="sessionIdCookieEnabled" value="true"/>
  51. <property name="sessionIdCookie" ref="sessionIdCookie"/>
  52. </bean>
  53. <!-- 安全管理器 -->
  54. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  55. <property name="realm" ref="userRealm"/>
  56. <property name="sessionManager" ref="sessionManager"/>
  57. <property name="cacheManager" ref="cacheManager"/>
  58. </bean>
  59. <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
  60. <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  61. <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
  62. <property name="arguments" ref="securityManager"/>
  63. </bean>
  64. <!-- 基于Form表单的身份验证过滤器 -->
  65. <strong>    <bean id="authcFilter" class="com.shiro.shiro.filter.MyFormAuthenticationFilter">
  66. <property name="usernameParam" value="username"/>
  67. <property name="passwordParam" value="password"/>
  68. <property name="failureKeyAttribute" value="shiroLoginFailure"/>
  69. </bean>
  70. <bean id="validateFilter" class="com.shiro.shiro.filter.ValidateFilter">
  71. <property name="verificationAbled" value="true"/>
  72. <property name="verificationParam" value="verificationParam"/>
  73. <property name="failureKeyAttribute" value="shiroLoginFailure"/>
  74. </bean></strong>
  75. <!-- Shiro的Web过滤器 -->
  76. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  77. <property name="securityManager" ref="securityManager"/>
  78. <property name="loginUrl" value="/login"/>
  79. <property name="filters">
  80. <util:map>
  81. <entry key="authc" value-ref="<strong>authcFilter</strong>"/>
  82. <entry key="sysUser" value-ref="sysUserFilter"/>
  83. <entry key="validateFilter" value-ref="<strong>validateFilter</strong>"/>
  84. <entry key="kickout" value-ref="<strong>kickoutSessionControlFilter</strong>"/>
  85. </util:map>
  86. </property>
  87. <property name="filterChainDefinitions">
  88. <value>
  89. /login = <strong>validateFilter</strong>,authc
  90. /logout = logout
  91. /authenticated = authc
  92. /** = <strong>kickout</strong>,user,sysUser
  93. </value>
  94. </property>
  95. </bean>
  96. <!-- currenuser  -->
  97. <bean id="sysUserFilter" class="com.shiro.shiro.filter.SysUserFilter"/>
  98. <!-- 并发踢出
  99. kickoutAfter:是否踢出后来登录的,默认是false
  100. kickoutUrl:被踢出后重定向到的地址
  101. maxSession:同一个用户最大的会话数,默认1
  102. -->
  103. <bean id="kickoutSessionControlFilter" class="com.shiro.shiro.filter.KickoutSessionControlFilter">
  104. <property name="cacheManager" ref="cacheManager"/>
  105. <property name="sessionManager" ref="sessionManager"/>
  106. <property name="kickoutAfter" value="false"/>
  107. <property name="maxSession" value="2"/>
  108. <property name="kickoutUrl" value="/login?kickout=1"/>
  109. </bean>
  110. <!-- Shiro生命周期处理器-->
  111. <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
  112. </beans>

[java] view plain copy

  1. </pre><pre name="code" class="java">自定义的

[java] view plain copy

  1. </pre><pre name="code" class="java"><pre name="code" class="java">package com.shiro.shiro.filter;
  2. import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
  3. import javax.servlet.ServletRequest;
  4. import javax.servlet.ServletResponse;
  5. /**
  6. * 自定义shiro FormAuthenticationFilter 表单过滤器
  7. * @author changliang
  8. *
  9. */
  10. public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
  11. /**
  12. * 授权是否失败
  13. */
  14. @Override
  15. protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
  16. if(request.getAttribute(getFailureKeyAttribute()) != null) {
  17. return true;
  18. }
  19. return super.onAccessDenied(request, response, mappedValue);
  20. }
  21. }

[java] view plain copy

  1. </pre>密码校验<pre>

[java] view plain copy

  1. <pre name="code" class="java">package com.shiro.shiro.filter;
  2. import org.apache.shiro.web.filter.AccessControlFilter;
  3. import org.apache.shiro.web.util.WebUtils;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import com.shiro.service.UserService;
  6. import javax.servlet.ServletRequest;
  7. import javax.servlet.ServletResponse;
  8. import javax.servlet.http.HttpServletRequest;
  9. /**
  10. * 验证码过滤器
  11. */
  12. public class ValidateFilter extends AccessControlFilter {
  13. @SuppressWarnings("unused")
  14. @Autowired
  15. private UserService userService;
  16. private boolean verificationAbled = true;                //是否开启验证码支持
  17. @SuppressWarnings("unused")
  18. private String verificationParam = "verificationParam";  //前台提交的验证码参数名
  19. private String failureKeyAttribute = "shiroLoginFailure"; //验证码验证失败后存储到的属性名
  20. public void setVerificationAbled(boolean verificationAbled) {
  21. this.verificationAbled = verificationAbled;
  22. }
  23. public void setVerificationParam(String verificationParam) {
  24. this.verificationParam = verificationParam;
  25. }
  26. public void setFailureKeyAttribute(String failureKeyAttribute) {
  27. this.failureKeyAttribute = failureKeyAttribute;
  28. }
  29. @Override
  30. protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
  31. //1、设置验证码是否开启属性,页面可以根据该属性来决定是否显示验证码
  32. request.setAttribute("verificationAbled", verificationAbled);
  33. HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
  34. //2、判断验证码是否禁用 或不是表单提交(允许访问)
  35. if (verificationAbled == false || !"post".equalsIgnoreCase(httpServletRequest.getMethod())) {
  36. return true;
  37. }
  38. <span style="color:#ff0000;"><strong> //3、此时是表单提交,验证验证码是否正确
  39. //TODO 增加自己的验证码校验
  40. //return  userService.verification(verificationParam);
  41. return true;</strong></span>
  42. }
  43. @Override
  44. protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
  45. //如果验证码失败了,存储失败key属性
  46. //在LoginController里过滤用到
  47. request.setAttribute(failureKeyAttribute, "<span style="color:#ff0000;">verification.error</span>");
  48. return true;
  49. }
  50. }

处理器

[java] view plain copy

  1. </pre><pre name="code" class="java"><pre name="code" class="java">package com.shiro.controller;
  2. import org.apache.shiro.authc.IncorrectCredentialsException;
  3. import org.apache.shiro.authc.UnknownAccountException;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.ui.Model;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import javax.servlet.http.HttpServletRequest;
  8. /**
  9. * 常见错误:
  10. *  subject.login()
  11. * DisabledAccountException(禁用的帐号)、
  12. * LockedAccountException(锁定的帐号)、
  13. * UnknownAccountException(错误的帐号)、
  14. * ExcessiveAttemptsException(登录失败次数过多)、
  15. * IncorrectCredentialsException (错误的凭证)、
  16. * ExpiredCredentialsException(过期的凭证)
  17. * @author changliang
  18. *
  19. */
  20. @Controller
  21. public class LoginController {
  22. @RequestMapping(value = "/login"    )
  23. public String showLoginForm(HttpServletRequest req, Model model) {
  24. String exceptionClassName = (String)req.getAttribute("shiroLoginFailure");
  25. String error = null;
  26. if(UnknownAccountException.class.getName().equals(exceptionClassName)) {
  27. error = "用户名/密码错误";
  28. } else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
  29. error = "用户名/密码错误";//错误的凭证
  30. }else if("<span style="color:#ff0000;">verification.error</span>".equals(exceptionClassName)) {
  31. error = "验证码错误";
  32. } else if(exceptionClassName != null) {
  33. error = "其他错误:" + exceptionClassName;
  34. }
  35. model.addAttribute("error", error);
  36. return "login";
  37. }
  38. }

参考 :http://jinnianshilongnian.iteye.com/blog/2049092

[java] view plain copy

  1. </pre><pre name="code" class="java">

[java] view plain copy

  1. </pre><pre name="code" class="java">

[java] view plain copy

  1. </pre><pre name="code" class="java">

[java] view plain copy

  1. </pre><pre name="code" class="java">

[java] view plain copy

  1. </pre>
时间: 2024-10-25 09:08:12

shiro + mybatis+ spring (只用shiro的密码校验和并发剔除)——不用权限之类的相关文章

Spring MVC + Shiro 实现权限验证

MAVEN的pom.xml 引入shiro(Spring MVC+mybatis 请参见上一章). <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.5</version> </dependency> <!-- http://mvnrepository.co

Shiro学习总结(10)——Spring集成Shiro

1.引入Shiro的Maven依赖 [html] view plain copy <!-- Spring 整合Shiro需要的依赖 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.1</version> </dependency> <dep

Shiro Demo:SpringBoot+Shiro+Druid+MyBatis

访问start.spring.io生成项目: 然后选择依赖: pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=&qu

web工程使用spring mvc+shiro进行权限控制

第1步:引入shiro相关jar包 ehcache-core-2.5.0.jar shiro-ehcache-1.2.3.jar shiro-core-1.2.3.jar shiro-web-1.2.3.jar shiro-spring-1.2.3.jar 第二步:web.xml配置 <!-- shiro的filter --> <!-- shiro过虑器,DelegatingFilterProxy通过代理模式将spring容器中的bean和filter关联起来 --> <fi

Spring整合Shiro做权限控制模块详细案例分析

1.引入Shiro的Maven依赖 <!-- Spring 整合Shiro需要的依赖 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId

第一章 Shiro简介——跟我学习springmvc shiro mybatis

1.1  简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大,但是在实际工作时可能并不需要那么复杂的东西,所以使用小而简单的Shiro就足够了.对于它俩到底哪个好,这个不必纠结,能更简单的解决项目问题就好了. 本教程只介绍基本的Shiro使用,不会过多分析源码等,重在使用. Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaS

Spring+SpringMVC+shiro+mysql(一)

最近要做个后台管理系统,就会设计到权限的管理控制,于是就想到 shiro ,下面是自己对Spring+shiro的一点点理解,记录下来,一起多探讨: 项目结构 1. pom.xml 配置 1.1. 版本属性信息配置 1 <properties> 2 <!-- base setting --> 3 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 4 <project.b

使用Shiro 集合Spring来实现权限控制

这只是笔记 web.xml中引入 spring-shiro.xml spring-shiro.xml : <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" x

shiro整合spring配置

shiro应用到项目中,一般都是通过spring来管理.下面就如何把shiro整理到spring中进行了讲解,及给出了配置的步骤: 一.pom.xml文件配置 本例子主要是介绍maven管理的web项目进行配置介绍,因此,首先需建立好一个maven管理的web项目(可参考本博客创建maven管理的web项目). pom.xml文件配置,主要是添加相关依赖的jar支持.因为整合到spring中需添加spring支持.具体配置参考配置代码: 1 <project xmlns="http://m