shiro多权限+spring+hibernate配置详解

其实不难,照着手册做就基本ok了,直接上代码,注释的很详细了

 

web.xml

 

  <?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Spring 刷新Introspector防止内存泄露 -->
<listener>
		<listener-class>
			org.springframework.web.util.IntrospectorCleanupListener
		</listener-class>
</listener>

<!--字符过滤器,统一使用utf-8编码 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>
			org.springframework.web.filter.CharacterEncodingFilter
		</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
 
    <filter-mapping>
      <filter-name>encodingFilter</filter-name>
      <url-pattern>*</url-pattern>
    </filter-mapping>


 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

<listener>  
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  
</listener>

<!-- 配置常见错误页面 -->

		

 <servlet>
  <servlet-name>spring</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>spring</servlet-name>
  <url-pattern>/</url-pattern>
 </servlet-mapping>
 <welcome-file-list>
  <welcome-file>/page/bidhome.jsp</welcome-file>
 </welcome-file-list>
 <login-config>
  <auth-method>BASIC</auth-method>
 </login-config>
 

<!-- add to avoid "Write operations are not allowed in read-only mode (FlushMode.MANUAL)"" error -->
<filter> 
   <filter-name>openSessionInViewFilter</filter-name> 
   <filter-class> 
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter 
   </filter-class> 
   <init-param> 
    <param-name>sessionFactoryBeanName</param-name> 
    <param-value>sessionFactory</param-value> 
   </init-param> 
   <init-param> 
            <param-name>singleSession</param-name> 
            <param-value>true</param-value>            
        </init-param> 
        <init-param> 
        <param-name> flushMode </param-name> 
   <param-value>AUTO </param-value>         
        </init-param> 
</filter>



    <!-- Shiro Filter is defined in the spring application context: -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>openSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
</web-app>
 

 

 

 

applicationContext.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" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:util="http://www.springframework.org/schema/util"
	
	
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	   		http://www.springframework.org/schema/context
	   		http://www.springframework.org/schema/context/spring-context-3.0.xsd
			http://www.springframework.org/schema/mvc 
			http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
			http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/util
     http://www.springframework.org/schema/util/spring-util-3.0.xsd"> 

	
	//数据源
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName"
			value="oracle.jdbc.driver.OracleDriver">
		</property>
		<property name="url" value="jdbc:oracle:thin:@172.31.112.87:1521:biddb">
		</property>
		<property name="username" value="bid"></property>
		<property name ="password" value="bid"></property>
	</bean>
	
        //定义sessionFactory
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		
		<property name="hibernateProperties">
			<props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.jdbc.fetch_size">100</prop>
<!--                 <prop key="hibernate.hbm2ddl.auto">create</prop> -->
<!--                 <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop> -->
            </props>
		</property>
				
		<property name="packagesToScan">
            <list>
                <value>com.bid.*</value>
            </list>
        </property>
     </bean>
	
	<!-- 声明一个 Hibernate 3 的事务管理器供代理类自动管理事务用 -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory"><ref local="sessionFactory" /></property>
	</bean>
	
	
    <bean id="hibernateTemplate"  class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
	<!-- 激活spring的注解. -->
	<context:annotation-config />
	
	<!-- Spring AOP auto-proxy creation (required to support Shiro annotations) -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <property name="proxyTargetClass" value="true"/> 
    </bean>

<!--  事务控制 -->
   <tx:annotation-driven  transaction-manager="transactionManager" proxy-target-class="true"/>
        

	<!-- 扫描注解组件并且自动的注入spring beans中. 
	例如,他会扫描@Controller 和@Service下的文件.所以确保此base-package设置正确. -->
	<context:component-scan base-package="com.bid.*" />
	<context:component-scan base-package="com.bid.security" />
	

	<!-- 配置注解驱动的Spring MVC Controller 的编程模型.注:次标签只在 Servlet MVC工作! -->
	<mvc:annotation-driven />
	<!-- 用注解来实现事务管理 -->

	
	<mvc:resources location="/resources/" mapping="/resources/**"/>  
	
	 <!-- =========================================================
         Shiro Components
         ========================================================= -->


    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
     
    <!-- add on 05.08, shiro work well -->
    <bean
		class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
   </bean>
	
	
	<!-- Shiro's main business-tier object for web-enabled applications (use 
		org.apache.shiro.web.mgt.DefaultWebSecurityManager instead when there is 
		no web environment) -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">	
		<property name="realm" ref="BidRealm" />
		
<!-- 	    配置session超时,10分钟,session配置无效,原因未知		 -->
<!--          <property name="sessionManager.globalSessionTimeout" value="600000"></property> -->

<!-- Uncomment this next property if you want heterogenous session access 
			or clusterable/distributable sessions. The default value is 'http' which 
			uses the Servlet container's HttpSession as the underlying Session implementation. 
			<property name="sessionMode" value="native"/> -->
    </bean>
    
     <!-- Define the Shiro Filter here (as a FactoryBean) instead of directly in web.xml -
         web.xml uses the DelegatingFilterProxy to access this bean.  This allows us
         to wire things with more control as well utilize nice Spring things such as
         PropertiesPlaceholderConfigurer and abstract beans or anything else we might need: -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
          <property name="unauthorizedUrl" value="/login"/>
        <property name="loginUrl" value="page/unauthorized.jsp"/>
        <property name="successUrl" value="home"/>
     
    </bean>
	</beans>

 

 进行认证和授权的realm

package com.uunemo.security;

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.UsernamePasswordToken;
import org.apache.shiro.authc.credential.Sha256CredentialsMatcher;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.uunemo.beans.Permission;
import com.uunemo.beans.Role;
import com.uunemo.beans.User;
import com.uunemo.daos.UserDAO;

/**
 * The Spring/Hibernate sample application's one and only configured Apache Shiro Realm.
 *
 * <p>Because a Realm is really just a security-specific DAO, we could have just made Hibernate calls directly
 * in the implementation and named it a 'HibernateRealm' or something similar.</p>
 *
 * <p>But we've decided to make the calls to the database using a UserDAO, since a DAO would be used in other areas
 * of a 'real' application in addition to here. We felt it better to use that same DAO to show code re-use.</p>
 */
@Component(value = "nemoRealm")
public class NemoRealm extends AuthorizingRealm {

    protected UserDAO userDAO = null;

    public NemoRealm() {
        setName("NemoRealm"); //This name must match the name in the User class's getPrincipals() method
//        setCredentialsMatcher(new Sha256CredentialsMatcher());
    }

    @Autowired
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }
   //登录时shiro会用到的方法
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        User user = (User)userDAO.findByName(token.getUsername()).get(0);
        if( user != null) {
            return new SimpleAuthenticationInfo(user.getUserid(), user.getPassword(), getName());
        } else {
            return null;
        }
    }

//权限验证
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
      //用的userid,当然也可以用username,
    	Integer userId = (Integer) principals.fromRealm(getName()).iterator().next();
        User user = userDAO.findById(userId);
        Set permissionSet = new HashSet<String>();
        if( user != null ) {
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            for( Role role : user.getRoles() ) {
                info.addRole(role.getRoleName());
                permissionSet.clear();
                for(Permission permission:role.getPermissions()){
                	permissionSet.add(permission.getPermissionName());
                }
               //将当前用户的permission加入info
                info.addStringPermissions( permissionSet);
            }
            return info;
        } else {
            return null;
        }
    }
}

 

 然后就可以使用啦,代码片段如下

   

//若非法登录,sihro会报异常,尝试在web.xml里无法捕获,因此采用下述方法在spring中捕获,异常捕获页面,跳转到登录页面
	@ExceptionHandler(org.apache.shiro.authz.UnauthenticatedException.class)
	public String handleException(){
		return BIDHOME;
	}
	
	
	//异常捕获页面,跳转到登录页面
		@ExceptionHandler(org.apache.shiro.authz.AuthorizationException.class)
		public String handleException2(){
			return BIDHOME;
		}
		
		//异常捕获页面,跳转到登录页面	
		@ExceptionHandler(java.lang.IllegalStateException.class)
		public String handleIllgalException(){
			return BIDHOME;
		}
		/**
		 * shiro有时logout再login会报这个错,框架bug。
		 * stackflow解释it looks like your UI framework is not regenerating the session
		 * @return
		 */
		@ExceptionHandler(org.apache.shiro.session.InvalidSessionException.class)	
		   public String handleInvalidSession(){
			return BIDHOME;
		}		
		
	
	//shiro的权限控制,在这里控制user和superuser可以访问
		@RequiresRoles(value={ConstantUtil.ROLE_USER,ConstantUtil.ROLE_SUPERUSER},logical=Logical.OR)
		@RequestMapping(value="duraldaypage")
		public String duralDayPageController(Model model){
			String duralDay= bidService.findDuralDay();
			if(duralDay==null||duralDay.equals("")){
				duralDay="0";
				model.addAttribute("duralday",duralDay);
			}else{
				model.addAttribute("duralday",duralDay);
			}
			return SETDURALDAYPAGE;
		}
		

 为hibernate实现,给出实体类 User.java

 

    

package com.uunemo.beans;

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

import javax.annotation.Generated;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

/**
 * User entity. @author MyEclipse Persistence Tools
 */

@Entity
@Table(name="user")
public class User {

	// Fields
   
	private Integer userid;
	private String username;
	private String password;
    private String realname;
    private String schoolname;
    private String email;	
    
   
    private String company;
    
    
    
    private Set<Role> roles = new HashSet<Role>();
    
    
    @ManyToMany(
			targetEntity = com.uunemo.beans.Role.class,
			cascade = {CascadeType.PERSIST, CascadeType.MERGE },
			fetch=FetchType.EAGER)
	@JoinTable(
			name = "user_role",
			joinColumns = @JoinColumn(name = "user_id"),
			inverseJoinColumns = @JoinColumn(name = "role_id"))
	public Set<Role> getRoles() {
		return roles;
	}


	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}

	 @Id
	    @GeneratedValue
	    @Column(name = "user_id",unique =true,nullable=false)
	public Integer getUserid() {
		return userid;
	}


	public void setUserid(Integer userid) {
		this.userid = userid;
	}

	@Column(name="user_name",unique=true,length=100 )
	public String getUsername() {
		return username;
	}


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

	 @Column(name="password",length=100)
	public String getPassword() {
		return password;
	}


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

	 @Column(name="real_name",length=100)
	public String getRealname() {
		return realname;
	}


	public void setRealname(String realname) {
		this.realname = realname;
	}

	 @Column(name="school_name",length=100)
	public String getSchoolname() {
		return schoolname;
	}


	public void setSchoolname(String schoolname) {
		this.schoolname = schoolname;
	}

	 @Column(name="email",length=100)
	public String getEmail() {
		return email;
	}


	public void setEmail(String email) {
		this.email = email;
	}


   @Column(name="company",length=25)
    public String getCompany() {
		return company;
	}


	public void setCompany(String company) {
		this.company = company;
	}


	
    
    public User(Integer user_id, String user_name, String password,
			String real_name, String school_name, String email) {
		super();
		this.userid = user_id;
		this.username = user_name;
		this.password = password;
		this.realname = real_name;
		this.schoolname = school_name;
		this.email = email;
	}

    
    public User() {
		// TODO Auto-generated constructor stub
	}


	
	

}

 实体类Role.java

 

package com.uunemo.beans;

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

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.uunemo.beans.Permission;

/**
 * Model object that represents a security role.
 */
@Entity
@Table(name="role")
public class Role {
    private int roleId;
    private String roleName;
    private Set<Permission> permissions = new HashSet<Permission>();

	@Id
	@GeneratedValue
	@Column(name="role_id",length=8,nullable=false)
    public int getId() {
        return roleId;
    }

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

    @Column(name="role_name",unique=true,length=20)
    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String role_name) {
        this.roleName = role_name;
    }
    
    
	@ManyToMany(targetEntity = com.uunemo.beans.Permission.class, cascade = {
			CascadeType.PERSIST, CascadeType.MERGE },
			fetch=FetchType.EAGER)
	@JoinTable(name = "role_permission", 
			joinColumns = @JoinColumn(name = "role_id"), 
			inverseJoinColumns = @JoinColumn(name = "permission_id"))
	public Set<Permission> getPermissions() {
		return permissions;
	}

	public void setPermissions(Set<Permission> permissions) {
		this.permissions = permissions;
	}

  
}

   

 

 

 

  

你可能感兴趣的:(spring,Hibernate,shiro)