zoukankan      html  css  js  c++  java
  • shiro + mybatis+ spring (只用shiro的密码校验和并发剔除)——不用权限之类

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

     

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

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

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

    此处用到了缓存,当然可以自己实现,把session存到数据库中然后判断操作
    1. </pre><pre name="code" class="java">再看下部分配置文件  
    1. </pre><pre name="code" class="java">  
    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.       
    60.     <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->  
    61.     <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
    62.         <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>  
    63.         <property name="arguments" ref="securityManager"/>  
    64.     </bean>  
    65.   
    66.     <!-- 基于Form表单的身份验证过滤器 -->  
    67. <strong>    <bean id="authcFilter" class="com.shiro.shiro.filter.MyFormAuthenticationFilter">  
    68.         <property name="usernameParam" value="username"/>  
    69.         <property name="passwordParam" value="password"/>  
    70.         <property name="failureKeyAttribute" value="shiroLoginFailure"/>  
    71.     </bean>  
    72.       
    73.      <bean id="validateFilter" class="com.shiro.shiro.filter.ValidateFilter">  
    74.         <property name="verificationAbled" value="true"/>  
    75.         <property name="verificationParam" value="verificationParam"/>  
    76.         <property name="failureKeyAttribute" value="shiroLoginFailure"/>  
    77.     </bean></strong>  
    78.        <!-- Shiro的Web过滤器 -->  
    79.     <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
    80.         <property name="securityManager" ref="securityManager"/>  
    81.         <property name="loginUrl" value="/login"/>  
    82.         <property name="filters">  
    83.             <util:map>  
    84.                 <entry key="authc" value-ref="<strong>authcFilter</strong>"/>  
    85.                 <entry key="sysUser" value-ref="sysUserFilter"/>  
    86.                 <entry key="validateFilter" value-ref="<strong>validateFilter</strong>"/>  
    87.                 <entry key="kickout" value-ref="<strong>kickoutSessionControlFilter</strong>"/>  
    88.             </util:map>  
    89.         </property>  
    90.         <property name="filterChainDefinitions">  
    91.             <value>  
    92.                  /login = <strong>validateFilter</strong>,authc  
    93.                  /logout = logout  
    94.                 /authenticated = authc  
    95.                 /** = <strong>kickout</strong>,user,sysUser  
    96.             </value>  
    97.         </property>  
    98.     </bean>  
    99.       
    100.     <!-- currenuser  -->  
    101.     <bean id="sysUserFilter" class="com.shiro.shiro.filter.SysUserFilter"/>  
    102.     <!-- 并发踢出   
    103.             kickoutAfter:是否踢出后来登录的,默认是false   
    104.             kickoutUrl:被踢出后重定向到的地址  
    105.             maxSession:同一个用户最大的会话数,默认1  
    106.      -->  
    107.     <bean id="kickoutSessionControlFilter" class="com.shiro.shiro.filter.KickoutSessionControlFilter">  
    108.         <property name="cacheManager" ref="cacheManager"/>  
    109.         <property name="sessionManager" ref="sessionManager"/>  
    110.         <property name="kickoutAfter" value="false"/>  
    111.         <property name="maxSession" value="2"/>  
    112.         <property name="kickoutUrl" value="/login?kickout=1"/>  
    113.     </bean>  
    114.     <!-- Shiro生命周期处理器-->  
    115.     <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  
    116.       
    117. </beans>  


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



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

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

    1. </pre><pre name="code" class="java">  
    1. </pre><pre name="code" class="java">  
    1. </pre><pre name="code" class="java">  
    1. </pre><pre name="code" class="java">  
    1. </pre>  
     
  • 相关阅读:
    [最优化理论与技术]线性规划
    [吴恩达深度学习]神经网络和深度学习
    Linux系统级性能分析工具perf的介绍与使用
    Oracle表变化趋势追踪记录 & 表 历史统计信息查看
    delete noprompt archivelog
    DEPLOYING ORACLE RAC DATABASE 12C RELEASE 2 ON RED HAT ENTERPRISE LINUX 7
    How to Modify SCAN Setting or SCAN Listener Port after Installation (Doc ID 972500.1)
    How to create a RAC Database Service With Physical Standby Role Option? (Doc ID 1129143.1)
    Oracle级联备库0数据丢失--重建控制文件并应用主库online redo logfile的激活方法
    Handling ORL and SRL (Resize) on Primary and Physical Standby in Data Guard Environment (Doc ID 1532566.1)
  • 原文地址:https://www.cnblogs.com/zouhao510/p/5609244.html
Copyright © 2011-2022 走看看