shiro实例

参考文档:
http://tool.oschina.net/apidocs/apidoc?api=shiro-core-1.2.0
https://www.cnblogs.com/learnhow/p/5694876.html


pom.xml配置:

```
<!-- shiro配置start -->
	<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-spring</artifactId>
		<version>1.2.2</version>
	</dependency>
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-ehcache</artifactId>
		<version>1.2.2</version>
	</dependency>
	<!-- 用这一个版本 不然会报  Another CacheManager with same name '' already exists in the same VM -->
	<dependency>
		<groupId>net.sf.ehcache</groupId>
		<artifactId>ehcache-core</artifactId>
		<version>2.4.8</version>
	</dependency>
	<!-- shiro配置end -->
```

web.xml配置:

```
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1" metadata-complete="true">
	<servlet > 
        <servlet-name>DispatcherServlet</servlet-name >
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class > 
        <init-param>  
            <param-name>contextConfigLocation</param-name > 
            <param-value>classpath:spring/spring-*.xml</param-value > 
        </init-param>
    </servlet> 
    <servlet-mapping> 
        <servlet-name>DispatcherServlet</servlet-name > 
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    
   
	<!-- 读取Spring配置文件 -->  
    <context-param>  
        <param-name>contextConfigLocation</param-name>  
        <param-value>  
            <!-- classpath:mybatis-config.xml  --> 
            classpath:spring/spring-*.xml  
        </param-value>  
    </context-param>  
    <listener>  
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
    </listener>  
	
	<!-- shiro配置 开始 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <async-supported>true</async-supported>
        <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>
    <!-- shiro配置 结束 -->
	
	<error-page>
    <error-code>404</error-code>
    <location>/errorPage/404.jsp</location>
	</error-page>
	<error-page>
    <error-code>500</error-code>
    <location>/errorPage/500.jsp</location>
	</error-page>
	
</web-app>

```

spring-shiro的配置如下:

```
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans    
						http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context    
                        http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/mvc    
                        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

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

	<!-- 配置凭证 -->
	<bean  id="credentialsMatcher" class="com.soecode.lyf.shiro.RetryLimitHashedCredentialsMatcher" >
		<constructor-arg ref="cachManager" />
		<!-- 加密方式 -->
		<property name="hashAlgorithmName" value="md5" />
		<!-- 加密次数 -->
		<property name="hashIterations" value="50" />
		<!-- 存储的凭据十六进制编码  -->
		<property name="storedCredentialsHexEncoded" value="true" />
	</bean>
	
	<!-- Realm实现 -->
	<bean id="userRealm" class="com.soecode.lyf.shiro.UserRealm">
		<property name="credentialsMatcher" ref="credentialsMatcher" />
	</bean>
	
	<!-- 安全管理器 -->
	<bean id = "securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" >
		<property name="realm" ref="userRealm" />
	</bean>
	
	<!-- shiro过滤器 -->
	<bean id="shiroFilter"  class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
		<property name="securityManager" ref="securityManager" />
        <property name="loginUrl" value="/" />
        <property name="unauthorizedUrl" value="/" />
        <property name="filterChainDefinitions">
            <value>
            <!-- 
            anon   无参,表示可匿名使用,可以理解为匿名用户或游客
            authc  无参,表示需认证才能使用 
            authc,roles[admin]    表示用户必需已通过认证,并拥有admin角色才可以正常发起'/admin'请求 
             -->
                <!-- /admin = authc,roles[admin] -->
                /static/** = anon
                /** = anon
            </value>
        </property>
	</bean>
	
	<!-- 设置生命周期 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
	
	<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true"/>
	
</beans>
```

ecache.xml配置如下:

```
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shirocache">
	<diskStore  path="java.io.tmpdir" />
	<!-- 
	name 缓存名称 
	maxElementsInMemory:缓存最大个数
	eternal:对象是否永久有效,一但设置了,timeout将不起作用
	timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,
			默认值是0,也就是可闲置时间无穷大
	timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false
			对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大
	overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中
	-->
	<!-- maxEntriesLocalHeap="2000" 无效-->
	<cache 
		name="passwordRetryCache" 
		eternal="false" 
		timeToIdleSeconds="1800" 
		timeToLiveSeconds="0"
		overflowToDisk="false" 
		statistics="true">
	</cache>
</ehcache>
```

ShiroTest.java用于获得md5加密后的密码用于测试,密码不能解密的话会报错所以密码不能随意添加:

```
public static void main(String[] args) {
        String hashAlgorithmName = "MD5";
        String credentials = "1";
        int hashIterations = 50;
        Object obj = new SimpleHash(hashAlgorithmName, credentials, null, hashIterations);
        System.out.println(obj);
    }
```

UserRealm.java代码如下:

```
package com.soecode.lyf.shiro;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.soecode.lyf.entity.IUser;
import com.soecode.lyf.service.IUserService;

public class UserRealm extends AuthorizingRealm {

	
	@Autowired
	private IUserService iUserService;
	
	
	/**
	 * 提供用户信息返回权限信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		String userName = (String)principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); 
		//设置当前用户拥有的角色
		Set<String> roles = new HashSet<String>();
		roles.add("r1");
		roles.add("r2");
		//加入角色名
		authorizationInfo.setRoles(roles);
		//设置当前用户的权限
		Set<String> permissionNames = new HashSet<String>();
		permissionNames.add("add");
		permissionNames.add("view");
		authorizationInfo.setStringPermissions(permissionNames);
		
		return authorizationInfo;
	}

	/**
	 * 提供账户信息返回认证信息
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String userName = (String)token.getPrincipal();
		IUser iUser = iUserService.findByUsername(userName);
		if(iUser==null){
			//用户不存在
			throw new UnknownAccountException();
		}
		
//		if(iUser.getLocked()=1){
//			throw new LockedAccountException();
//		}
		
//		iUser.setPassword("003d75ffdd78e6469723594eae0e21aa");
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(iUser.getLoginUser(),
				iUser.getPassword(), getName());
		
		return simpleAuthenticationInfo;
	}

}

```

RetryLimitHashedCredentialsMatcher.java的代码如下:

```
package com.soecode.lyf.shiro;

import java.util.concurrent.atomic.AtomicInteger;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
/**
 * 匹配用户登录使用的令牌和数据库中保存的用户信息是否匹配
 * @author an
 *
 */
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
	static{
		System.out.println(">>>>>>>>>>>RetryLimitHashedCredentialsMatcher<<<<<<<<<<<");
	}
	
	//声明一个缓存接口
	private Cache<String,AtomicInteger> cache;
	
	public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager){
		cache=cacheManager.getCache("passwordRetryCache");
	}
	
	@Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
			
		String username = (String)token.getPrincipal();
		AtomicInteger retryCount = cache.get(username);
		if(retryCount == null){
			retryCount = new AtomicInteger(0);
			cache.put(username, retryCount);
		}
		
		if(retryCount.incrementAndGet()>5){
			throw new ExcessiveAttemptsException();
		}
		
		boolean match = super.doCredentialsMatch(token, info);
		
		if(match){
			cache.remove(username);
		}
		
		return match;
		
		
    }
	
	
}

```
IUserController.java的代码如下:

```
package com.soecode.lyf.web;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.soecode.lyf.entity.IUser;
import com.soecode.lyf.service.IUserService;
import com.soecode.lyf.util.StringUtils;

@Controller
@RequestMapping("/main")
public class IUserController {
	
	Logger logger = Logger.getLogger(IUserController.class);
	
	private static final String main_page="main";
	
	private static final String index_page="main";
	
	@Resource
	private IUserService iUserService;
	
	@Autowired
    private HttpSession session;
	
	@Autowired
	private SecurityManager securityManager;
	
	
	@RequestMapping("/toMainPage.do")
	public ModelAndView toMainPage(String loginUser,String password,HttpServletRequest request){
		
		ModelAndView mv = new ModelAndView();
		mv.setViewName("index");
		UsernamePasswordToken token = new UsernamePasswordToken(loginUser,password);
		//记住我
//		token.setRememberMe(true);
		Subject subject = SecurityUtils.getSubject();
		
		String userName = (String)subject.getSession().getAttribute("userName");
		if(!StringUtils.isBlank(userName)){
			mv.setViewName(main_page);
			return mv;
		}
		
		try {
			subject.login(token);
		} catch (IncorrectCredentialsException ice) {
            // 捕获密码错误异常
            mv.addObject("message", "密码错误!");
            return mv;
        } catch (UnknownAccountException uae) {
            // 捕获未知用户名异常
            mv.addObject("message", "登录名错误!");
            return mv;
        } catch (ExcessiveAttemptsException eae) {
            // 捕获错误登录过多的异常
            mv.addObject("message", "登录失败超过五次,暂时无法登录!");
            return mv;
        }
		
		IUser user = iUserService.findByUsername(loginUser);
		request.getSession().setAttribute("userName", user.getUserName());
		
		logger.debug("进入跳转的方法");
		mv.setViewName(main_page);
		return mv;
	}
	
	/**
	 * 登出
	 */
	@RequestMapping("/logout.do")
	public ModelAndView logout(){
		Subject subject = SecurityUtils.getSubject();
		if(subject.isAuthenticated()){
			subject.logout();
		}
		ModelAndView mv = new ModelAndView();
		mv.setViewName("index");
		return mv;
	}
	
}


```

main.jsp代码如下:

```
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
    <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h1>这里是首页</h1>
<h2>欢迎:${userName}</h2>
<shiro:hasRole name="r1">
    用户[<shiro:principal/>]拥有角色r1<br/>
</shiro:hasRole> 
<shiro:hasRole name="r3">
    用户[<shiro:principal/>]拥有角色r3<br/>
</shiro:hasRole> 
</body>
</html>

```

转载于:https://my.oschina.net/u/3170610/blog/1818768

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值