shiro+ssm详细整合教程

第一步

这是一个很好的shiro学习网址:http://jinnianshilongnian.iteye.com/blog/2049092

在进行下面的步骤之前,您必须先拥有一个maven管理的ssm项目

第二步:准备数据库

这里需要我们准备shiro需要的权限表

shiro+ssm详细整合教程

这里我给大家提供mysql的建表脚本,直接运行即可



SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `sys_permissions`
-- ----------------------------
DROP TABLE IF EXISTS `sys_permissions`;
CREATE TABLE `sys_permissions` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `permission` varchar(100) DEFAULT NULL COMMENT '权限名',
  `description` varchar(100) DEFAULT NULL COMMENT '描述',
  `available` int(11) DEFAULT NULL COMMENT '是否可用,0表示可用,1表示不可用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_permissions
-- ----------------------------
INSERT INTO `sys_permissions` VALUES ('1', 'user:create', '添加用户', '0');
INSERT INTO `sys_permissions` VALUES ('2', 'user:read', '查询用户', '0');
INSERT INTO `sys_permissions` VALUES ('3', 'user:update', '修改用户', '0');
INSERT INTO `sys_permissions` VALUES ('4', 'user:delete', '删除用户', '0');
INSERT INTO `sys_permissions` VALUES ('5', 'book:create', '添加书籍', '0');
INSERT INTO `sys_permissions` VALUES ('6', 'book:read', '查询书籍', '0');
INSERT INTO `sys_permissions` VALUES ('7', 'book:update', '修改书籍', '0');
INSERT INTO `sys_permissions` VALUES ('8', 'book:delete', '删除书籍', '0');

-- ----------------------------
-- Table structure for `sys_roles`
-- ----------------------------
DROP TABLE IF EXISTS `sys_roles`;
CREATE TABLE `sys_roles` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `role` varchar(100) DEFAULT NULL COMMENT '角色名',
  `description` varchar(100) DEFAULT NULL COMMENT '描述',
  `available` int(11) DEFAULT NULL COMMENT '是否可用,0表示可用,1表示不可用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_roles
-- ----------------------------
INSERT INTO `sys_roles` VALUES ('1', 'super_admin', '*别的角色', '0');
INSERT INTO `sys_roles` VALUES ('2', 'admin', '普通角色', '0');

-- ----------------------------
-- Table structure for `sys_roles_permissions`
-- ----------------------------
DROP TABLE IF EXISTS `sys_roles_permissions`;
CREATE TABLE `sys_roles_permissions` (
  `role_id` int(10) unsigned NOT NULL COMMENT '角色id',
  `permission_id` int(10) unsigned NOT NULL COMMENT '权限id',
  PRIMARY KEY (`role_id`,`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_roles_permissions
-- ----------------------------
INSERT INTO `sys_roles_permissions` VALUES ('1', '1');
INSERT INTO `sys_roles_permissions` VALUES ('1', '2');
INSERT INTO `sys_roles_permissions` VALUES ('1', '3');
INSERT INTO `sys_roles_permissions` VALUES ('1', '4');
INSERT INTO `sys_roles_permissions` VALUES ('1', '5');
INSERT INTO `sys_roles_permissions` VALUES ('1', '6');
INSERT INTO `sys_roles_permissions` VALUES ('1', '7');
INSERT INTO `sys_roles_permissions` VALUES ('1', '8');

-- ----------------------------
-- Table structure for `sys_users`
-- ----------------------------
DROP TABLE IF EXISTS `sys_users`;
CREATE TABLE `sys_users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `username` varchar(100) DEFAULT NULL COMMENT '用户名',
  `password` varchar(100) DEFAULT NULL COMMENT '用户名',
  `salt` varchar(100) DEFAULT NULL COMMENT '盐',
  `locked` int(11) DEFAULT NULL COMMENT '是否锁住,0表示未锁,1表示锁住',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_users
-- ----------------------------
INSERT INTO `sys_users` VALUES ('2', 'xl', '23d49e2b98d2a95d82ecd30c0cb5713f', '9ce31fdc59048b65a282a297335acefc', '0');

-- ----------------------------
-- Table structure for `sys_users_roles`
-- ----------------------------
DROP TABLE IF EXISTS `sys_users_roles`;
CREATE TABLE `sys_users_roles` (
  `user_id` int(10) unsigned NOT NULL COMMENT '用户id',
  `role_id` int(10) unsigned NOT NULL COMMENT '角色id',
  PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_users_roles
-- ----------------------------
INSERT INTO `sys_users_roles` VALUES ('2', '1');
  第三步:pom中导入shiro依赖jar包
<dependency>
    	<groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.2.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.2.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.2.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-quartz</artifactId>
        <version>1.2.2</version>
    </dependency>

    <dependency>
    	<groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.2.2</version>
    </dependency>
	<dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>

 

第四步:拷贝spring-shiro-web.xml到resources目录
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- 缓存管理器,使用Ehcache实现 -->
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
    </bean>

    <!-- 凭证匹配器,验证密码是否正确,用 下面的类去验证-->
    <bean id="credentialsMatcher" class="sdibt.fight.util.RetryLimitHashedCredentialsMatcher">
        <constructor-arg ref="cacheManager"/>
        <property name="hashAlgorithmName" value="md5"/>
        <property name="hashIterations" value="2"/>
        <property name="storedCredentialsHexEncoded" value="true"/>
    </bean>

    <!-- Realm实现 -->
    <bean id="userRealm" class="sdibt.fight.util.UserRealm">
        <property name="sysUserService" ref="sysUserService"/>
        <property name="credentialsMatcher" ref="credentialsMatcher"/>
        <!-- 启用缓存 -->
        <property name="cachingEnabled" value="true"/>
        <!-- 启用身份验证缓存,即缓存AuthenticationInfo信息 -->
        <property name="authenticationCachingEnabled" value="false"/>
        <!-- 缓存AuthenticationInfo信息的缓存名称 -->
        <property name="authenticationCacheName" value="authenticationCache"/>
        <!-- 启用授权缓存,即缓存AuthorizationInfo信息 -->
        <property name="authorizationCachingEnabled" value="true"/>
        <!-- 缓存AuthorizationInfo信息的缓存名称 -->
        <property name="authorizationCacheName" value="authorizationCache"/>
    </bean>

    <!-- 会话ID生成器 -->
    <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>

    <!-- 会话Cookie模板 -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="sid"/>
        <property name="httpOnly" value="true"/>
        <!-- maxAge=-1表示浏览器关闭时失效此Cookie -->
        <property name="maxAge" value="-1"/>
    </bean>
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="rememberMe"/>
        <property name="httpOnly" value="true"/>
        <!-- 单位为s-->
        <property name="maxAge" value="1800"/>
    </bean>

    <!-- rememberMe管理器 -->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <!-- rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)-->
        <property name="cipherKey"
                  value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
        <property name="cookie" ref="rememberMeCookie"/>
    </bean>
    
    <bean id="formAuthenticationFilter"   
		class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">  
    	<property name="rememberMeParam" value="rememberMe"/>  
	</bean>

    <!-- 会话DAO -->
    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
        <property name="activeSessionsCacheName" value="shiro-activeSessionCache"/>
        <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
    </bean>

    <!-- 会话验证调度器 -->
    <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
        <property name="sessionValidationInterval" value="1800000"/>
        <property name="sessionManager" ref="sessionManager"/>
    </bean>

    <!-- 会话管理器 -->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="globalSessionTimeout" value="1800000"/>
        <property name="deleteInvalidSessions" value="true"/>
        <property name="sessionValidationSchedulerEnabled" value="true"/>
        <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
        <property name="sessionDAO" ref="sessionDAO"/>
        <property name="sessionIdCookieEnabled" value="true"/>
        <property name="sessionIdCookie" ref="sessionIdCookie"/>
    </bean>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userRealm"/>
        <property name="sessionManager" ref="sessionManager"/>
        <property name="cacheManager" ref="cacheManager"/>
        <property name="rememberMeManager" ref="rememberMeManager"/>
    </bean>

    <!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
        <property name="arguments" ref="securityManager"/>
    </bean>

     

    <!-- Shiro的Web过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/login.jsp"/>
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <property name="filterChainDefinitions">
        	<value>
        		<!-- 对于过滤器,一般这样使用:
				访问一般网页,如个人在主页之类的,我们使用user拦截器即可,user拦截器只要用户登录
				(isRemembered()==true or isAuthenticated()==true)过即可访问成功
				访问特殊网页,如我的订单,提交订单页面,我们使用authc拦截器即可,authc拦截器会判断用户是否是通过
				Subject.login(isAuthenticated()==true)登录的,如果是才放行,否则会跳转到登录页面叫你重新登录 -->
            	/login.jsp = anon
                /sysUser/doLogin = anon
                /**=user
               
            </value>
        </property>
    </bean>

    <!-- Shiro生命周期处理器-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

</beans>

 

第五步、在web.xml中加入shiro过滤器,并让监听器加载spring-shiro-web.xml,注意下面只是web.xml的部分内容
<!-- 配置shiro过滤器,且该过滤器必须配置在dispatcherServlet之前 ,DelegatingFilterProxy类会自动到Spring容器中
  	查找名字为shiroFilter的bean并把filter请求交给它处理-->
  <filter>
  	<filter-name>shiroFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	<init-param>
		<param-name>targetFilterLifecycle</param-name>
		<param-value>true</param-value>
	</init-param>
  </filter>
  <filter-mapping>
	<filter-name>shiroFilter</filter-name>
	<url-pattern>/*</url-pattern>
  </filter-mapping>

<!-- 配置监听器,监听spring上下文中对象的创建.注意:mvc配置文件应最后被加载,因为controller依赖service -->
    <context-param>  
    	<param-name>contextConfigLocation</param-name>  
        <param-value>  
        	classpath:spring-mybatis.xml, 
        	<!-- 因为shiro配置文件里依赖了service,因此必须先加载spring-mybatis.xml -->
        	classpath:spring-shiro-web.xml
        </param-value>  
    </context-param> 
    <listener>
    	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

 

第六步、准备登录界面login.jsp
<form action="${pageContext.request.contextPath }/sysUser/doLogin" method="post">
		用户名:<input type="text" name="username"><br>
		密码:<input type="password" name="password"><br>
		记住我:<input type="checkbox" value="true" name="rememberMe"><br>
		<input type="submit" value="登录">
		
	</form>

 

第七步、SysUserController类
@Controller
@RequestMapping("/sysUser")
public class SysUserController {
	@Resource
	private SysUserService sysUserService;

	public SysUserService getSysUserService() {
		return sysUserService;
	}

	public void setSysUserService(SysUserService sysUserService) {
		this.sysUserService = sysUserService;
	}
	
	@RequestMapping("/doLogin")
	public String doLogin(SysUser sysUser,String rememberMe) {
		System.out.println(rememberMe);
		
		//得到Subject,通过SecurityUtils得到Subject,其会自动绑定到当前线程;如果在web环境在请求结束时需要解除绑定
	    Subject subject = SecurityUtils.getSubject();  
	    //创建用户名/密码身份验证Token(即用户身份/凭证)  
	    UsernamePasswordToken token=new UsernamePasswordToken(sysUser.getUsername(),sysUser.getPassword());  
	    if(rememberMe!=null) {
	    	//当checkbox勾选之后,rememberMe就不为null,此时启用rememberMe
	    	token.setRememberMe(true);
	    }else {
	    	//关闭rememberMe
	    	token.setRememberMe(false);
	    }
	    try {  
	        /*
	         * 身份验证,调用subject.login方法进行登录,其会自动委托给SecurityManager.login方法进行登录
	         * 通过login登录,如果登录失败将抛出相应的AuthenticationException,
	         * 如果登录成功调用subject.isAuthenticated就会返回true,即已经通过身份验证
	         * 如果isRemembered返回true,表示是通过记住我功能登录的而不是调用login方法登录的
	         * isAuthenticated/isRemembered是互斥的,即如果其中一个返回true,另一个返回false
	         */
	        subject.login(token);  
	        
	    } catch (AuthenticationException e) { 
	    	/*
	    	 *  如果身份验证失败请捕获AuthenticationException或其子类,常见的如:
	    	 *  DisabledAccountException(禁用的帐号)、
	    	 *  LockedAccountException(锁定的帐号)、
	    	 *  UnknownAccountException(错误的帐号)、
	    	 *  ExcessiveAttemptsException(登录失败次数过多)、
	    	 *  IncorrectCredentialsException (错误的凭证)、
	    	 *  ExpiredCredentialsException(过期的凭证)等,具体请查看其继承关系
	    	 *  对于页面的错误消息展示,最好使用如“用户名/密码错误”而不是“用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库
	    	 */
	    	
	        return "login_failed";
	    }  
	    
	    
		return "main";
	}
	
	@ResponseBody
	@RequestMapping("/saveSysUser")
	public String saveSysUser(SysUser sysUser) {
		try {
			//如果b为true,说明添加成功
			boolean b = this.sysUserService.saveSysUser(sysUser);
			return "添加成功";
		} catch (Exception e) {
			//如果有异常,说明添加失败
			return "添加失败";
		}
		
	}
	
	@RequestMapping("/doLogout")
	public String doLogout() {
		//退出操作后一定要重定向页面
		Subject subject = SecurityUtils.getSubject(); 
	    subject.logout();
	    return "login";
	}
	

}

 

第八步、SysUserService接口
public interface SysUserService {
	SysUser getUserByUsername(String username);
	Set<String> listRoles(String username);
	Set<String> listPermissions(String username);
	boolean saveSysUser(SysUser sysUser);
}

 

第九步、SysUserServiceImpl实现类
@Service("sysUserService")
public class SysUserServiceImpl implements SysUserService{
	@Resource
	private SysUserDao sysUserDao;

	public SysUserDao getSysUserDao() {
		return sysUserDao;
	}

	public void setSysUserDao(SysUserDao sysUserDao) {
		this.sysUserDao = sysUserDao;
	}

	@Override
	public SysUser getUserByUsername(String username) {
		return this.sysUserDao.getUserByUsername(username);
	}

	@Override
	public Set<String> listRoles(String username) {
		return this.sysUserDao.listRoles(username);
	}

	@Override
	public Set<String> listPermissions(String username) {
		return this.sysUserDao.listPermissions(username);
	}

	/**
	 * 添加用户
	 */
	@Override
	@Transactional
	public boolean saveSysUser(SysUser sysUser) {
		//service里主要的工作是,将随机salt和加密后的密码存进数据库
		SysUser sysUserToDB = new PasswordHelper().encryptPassword(sysUser);
		//保存最终进入数据库的sysUser
		int rows = this.sysUserDao.saveSysUser(sysUserToDB);
		if(rows==1) {
			return true;
		}else {
			throw new RuntimeException();
		}
	}

	
	
}

 

第十步、SysUserDao接口
public interface SysUserDao {
	SysUser getUserByUsername(String username);
	Set<String> listRoles(String username);
	Set<String> listPermissions(String username);
	int saveSysUser(SysUser sysUser);
}

 

第十一步、SysUser实体类
public class SysUser implements Serializable {
    private int id;
    private String username;
    private String password;
    private String salt;
    private int locked;
   
    public String getCredentialsSalt() {
        return username + salt;
    }

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getSalt() {
		return salt;
	}

	public void setSalt(String salt) {
		this.salt = salt;
	}

	public int getLocked() {
		return locked;
	}

	public void setLocked(int locked) {
		this.locked = locked;
	}

}

 

第十二步、SysUser.xml映射文件
<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="sdibt.fight.dao.SysUserDao">
	<!-- 根据用户名查找用户 -->
	<select id="getUserByUsername" parameterType="java.lang.String" resultType="sdibt.fight.entity.SysUser">
		select * from sys_users where username=#{username} and locked=0
	</select>
	
	<!-- 查询用户所有角色 -->
	<select id="listRoles" parameterType="java.lang.String" resultType="java.lang.String">
		select r.role from sys_users u inner join sys_users_roles ur on u.id=ur.user_id 
		inner join sys_roles r on ur.role_id=r.id where u.username=#{username} and u.locked=0
		and r.available=0
	</select>
	
	<!-- 查询用户所有权限,返回值是权限名集合 -->
	<select id="listPermissions" parameterType="java.lang.String" resultType="java.lang.String">
		select p.permission from sys_users u inner join sys_users_roles ur on u.id=ur.user_id 
		inner join sys_roles r on ur.role_id=r.id inner join sys_roles_permissions rp 
		on r.id=rp.role_id inner join sys_permissions p on p.id=rp.permission_id
		where u.username=#{username} and u.locked=0 and r.available=0 and p.available=0
	</select>
	
	
 	
 	<!-- 添加用户 -->
 	<insert id="saveSysUser" parameterType="sdibt.fight.entity.SysUser">
 		insert into sys_users(username,password,salt,locked) 
 		values(#{username},#{password},#{salt},#{locked})
 	</insert>
</mapper>

 

第十三步、UserRealm类,用于获取安全数据源,建议放到util包下
public class UserRealm extends AuthorizingRealm {

    private SysUserService sysUserService;
	
    public SysUserService getSysUserService() {
		return sysUserService;
	}

	public void setSysUserService(SysUserService sysUserService) {
		this.sysUserService = sysUserService;
	}

	/**
	 * 获取权限信息,只有在身份验证成功后才调用此方法获取权限信息
	 */
	@Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//获取用户名
        String username = (String)principals.getPrimaryPrincipal();
        //new一个授权信息
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //给授权信息设置角色集合,只能放角色名
        authorizationInfo.setRoles(sysUserService.listRoles(username));
        //给授权信息设置权限集合
        authorizationInfo.setStringPermissions(sysUserService.listPermissions(username));
        //返回用户授权信息
        return authorizationInfo;
    }

	/**
	 * 获取身份验证信息
	 */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    	
    	//获取用户名
        String username = (String)token.getPrincipal();
        //根据用户名获取User对象
        SysUser user = sysUserService.getUserByUsername(username);

        if(user == null) {
        	//找不到账号
            throw new UnknownAccountException();
        }

        if(user.getLocked()==1) {
        	//帐号锁定
            throw new LockedAccountException();
        }

        /*
         * new一个身份验证信息
         */
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
        		//用户名
                user.getUsername(),
                //从数据库中查出的密文密码
                user.getPassword(),
                //credentialsSalt=username+salt
                ByteSource.Util.bytes(user.getCredentialsSalt()),
                //realm名称
                getName()
        );
        Session session = getSession();
        //将当前用户放进session
        session.setAttribute("username", username);
        /*
         * 返回身份验证信息,将交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
	     * CredentialsMatcher使用盐加密传入的明文密码和此处的密文密码进行匹配
         */
        return authenticationInfo;
    }
    /**
     * 获取shiro封装的session
     */
    private Session getSession(){  
        try{  
            Subject subject = SecurityUtils.getSubject();  
            Session session = subject.getSession(false);  
            if (session == null){  
                session = subject.getSession();  
            }  
            if (session != null){  
                return session;  
            }  
        }catch (InvalidSessionException e){  
              
        }  
        return null;  
    }  
    //以下是一些清空realm缓存的方法
    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }

}

 

第十四步、RetryLimitHashedCredentialsMatcher类,用于验证密码是否正确,建议放到util包下
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    private Cache<String, AtomicInteger> passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
    	//获取用户名
        String username = (String)token.getPrincipal();
        //从缓存中获取该用户已经输入密码的尝试次数
        AtomicInteger retryCount = passwordRetryCache.get(username);
        if(retryCount == null) {
            retryCount = new AtomicInteger(0);
            //将用户输入密码的尝试次数缓存起来
            passwordRetryCache.put(username, retryCount);
        }
        if(retryCount.incrementAndGet() > 5) {
            //密码输入次数超过五次
            throw new ExcessiveAttemptsException();
        }
        /*
         * token是表单上输入的用户名和密码,info是从数据中查的信息,将作密码比对
         */
        boolean matches = super.doCredentialsMatch(token, info);
        if(matches) {
            //清楚尝试次数
            passwordRetryCache.remove(username);
        }
        return matches;
    }
}

 

第十五步、PasswordHelper类,密码帮助类,建议放到util包下
public class PasswordHelper {

    private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
    private String algorithmName = "md5";
    private int hashIterations = 2;

    public void setRandomNumberGenerator(RandomNumberGenerator randomNumberGenerator) {
        this.randomNumberGenerator = randomNumberGenerator;
    }

    public void setAlgorithmName(String algorithmName) {
        this.algorithmName = algorithmName;
    }

    public void setHashIterations(int hashIterations) {
        this.hashIterations = hashIterations;
    }
    
	/**
	 * 加密密码
	 */
    public SysUser encryptPassword(SysUser sysUser) {
    	//设置随机salt
        sysUser.setSalt(randomNumberGenerator.nextBytes().toHex());
        //密码明文+随机salt=密码密文         
        String newPassword = new SimpleHash(
                algorithmName,
                sysUser.getPassword(),
                //credentialsSalt=username+salt
                ByteSource.Util.bytes(sysUser.getCredentialsSalt()),
                hashIterations).toHex();
        //设置密码密文
        sysUser.setPassword(newPassword);
        
        return sysUser;
    }
    
   
}

 

第十六步、准备其他jsp页面

一、main.jsp

<!-- 相当于Subject.getPrincipals().oneByType(String.class) -->
	当前用户:<shiro:principal type="java.lang.String"/><br>
	有无超级管理员权限:
	<shiro:hasRole name="super_admin">  
    	有
	</shiro:hasRole> 
	<br>
	有无普通管理员权限:
	<shiro:hasRole name="admin">  
    	有
	</shiro:hasRole> 
	<br>
	有哪些权限:
	<shiro:hasPermission name="user:create">  
    	<a href="${pageContext.request.contextPath }/sysuser_add.jsp">添加用户</a>
	</shiro:hasPermission>
	<shiro:hasPermission name="user:read">  
    	<a href="#">查询用户</a>
	</shiro:hasPermission>
	<shiro:hasPermission name="user:update">  
    	<a href="#">修改用户</a>
	</shiro:hasPermission>
	<shiro:hasPermission name="user:delete">  
    	<a href="#">删除用户</a>
	</shiro:hasPermission>
	<br>
	<a href="${pageContext.request.contextPath }/sysUser/doLogout">退出登录</a>

二、sysuser_add.jsp

<form action="${pageContext.request.contextPath }/sysUser/saveSysUser" method="post">
		用户名:<input type="text" name="username">
		密码:<input type="password" name="password">
		是否锁住用户:<input type="text" name="locked">
		<input type="submit" value="添加用户">
		
	</form>

三、login_failed.jsp

就显示一句登录失败即可

四、unauthorized.jsp

就显示一句您没有权限即可

 

第十七步、运行测试

登录入口为login.jsp,用户名xl,密码ok,如果登录成功,将跳到main.jsp

上一篇:system sys,sysoper sysdba 的区别


下一篇:shiro中doGetAuthorizationInfo授权方法不执行问题