Apache Shiro权限框架在SpringMVC+Hibernate中的应用

来源:互联网 发布:淘宝双十一销量排行 编辑:程序博客网 时间:2024/04/30 10:53

Apache Shiro权限框架在SpringMVC+Hibernate中的应用

开源中国

开源中国

发表于 2014-08-23 00:11:52

       在做网站开发中,用户权限必须要考虑的,权限这个东西很重要,它规定了用户在使用中能进行哪些操作,和不能进行哪些操作;我们完全可以使用过滤器来进行权限的操作,但是有了权限框架之后,使用起来会非常的方便,一般在公司里面做网站开发常用的权限框架有Spring的Security框架,和Apache的Shiro框架;Spring Security框架在使用上相比Shiro来说要更复杂一些,并且它限制了数据库该怎么去建表,只有按它的要求去建表,才能达到你想要的效果。下面我主要介绍一下Shiro框架的使用,由于本人也是初学者,所写难免会有些不合理的地方,望各位指正;

       使用Apache Shiro框架的步骤:

1.导入相应的jar包,我使用的是maven来管理的,pom.xml配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.kaishengit</groupId><artifactId>springmvctest</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version> <name>springmvctest Maven Webapp</name><url>http://maven.apache.org</url><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>3.2.4.RELEASE</version></dependency><dependency><groupId>org.codehaus.jackson</groupId><artifactId>jackson-mapper-asl</artifactId><version>1.9.10</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>3.2.4.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>3.2.4.RELEASE</version></dependency><!-- Hibernate --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>4.2.5.Final</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-ehcache</artifactId><version>4.2.5.Final</version></dependency><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId><version>2.7.2</version></dependency><dependency><groupId>commons-dbcp</groupId><artifactId>commons-dbcp</artifactId><version>1.4</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.26</version></dependency><dependency><groupId>javax.inject</groupId><artifactId>javax.inject</artifactId><version>1</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.0.1.Final</version></dependency> <!--Apache 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-spring</artifactId><version>1.2.2</version></dependency></dependencies><build><finalName>springmvctest</finalName><plugins><plugin><groupId>org.mortbay.jetty</groupId><artifactId>jetty-maven-plugin</artifactId><configuration><scanIntervalSeconds>10</scanIntervalSeconds><webApp><contextPath>/</contextPath></webApp><connectors> <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector"><port>80</port><maxIdleTime>60000</maxIdleTime></connector></connectors></configuration></plugin></plugins></build></project>

2.在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/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>Archetype Created Web Application</display-name> <!-- OpenSessionInView --><filter><filter-name>opensessioninview</filter-name><filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class></filter><filter-mapping><filter-name>opensessioninview</filter-name><url-pattern>/*</url-pattern></filter-mapping> <!-- SpringMVC中央控制器 --><servlet><servlet-name>mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>mvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping> <!-- Spring监听器 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext*.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></filter><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>

3.使用SpringMVC:在/WEB-INF/路径下配置springmvc-servlet.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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"><!-- 自动扫描 --><context:component-scan base-package="com.kaishengit.controller"><context:include-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan><mvc:annotation-driven/><!-- 静态资源访问 --><mvc:resources location="/static/"mapping="/static/**"/><!-- 视图解析器 --><bean id="viewResolver"class="org.springframework.web.servlet.view.UrlBasedViewResolver"><property name="viewClass"value="org.springframework.web.servlet.view.JstlView"/><property name="prefix"value="/WEB-INF/views/"/><property name="suffix"value=".jsp"/></bean><!-- 文件上传解析器 --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 配置最大上传文件的大小 --><property name="maxUploadSize"value="1000000"/></bean><!-- 拦截器 --><mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.kaishengit.controller.MyInterceptor"><property name="excluedUrls"><list><value>/home</value></list></property></bean></mvc:interceptor></mvc:interceptors><!-- 异常 --><bean id="handlerExceptionResolver"class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><prop key="com.kaishengit.exception.AuthorizationException">redirect:/home</prop></props></property></bean></beans>

 4.配置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:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 自动扫描所有的注解,排除掉controller不扫描 --><context:component-scan base-package="com.kaishengit"><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan><!-- 加载ClassPath中的properties文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 基于Hibernate的事务管理器 --><bean id="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager"><property name="sessionFactory"ref="sessionFactory"></property></bean><!-- 配置数据源 --><bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName"value="${jdbc.driver}"/><property name="url"value="${jdbc.url}"/><property name="username"value="${jdbc.username}"/><property name="password"value="${jdbc.password}"/></bean><!-- 基于注解 --><tx:annotation-driven transaction-manager="transactionManager"/><!-- SessionFactory --><bean id="sessionFactory"class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"><property name="dataSource"ref="dataSource"/><!-- 实体类pojo所在的包 --><property name="packagesToScan"value="com.kaishengit.pojo"/><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop></props></property></bean></beans>

5.将配置在applicationContext.xml中的shiro独立出来,新建applicationContext-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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><bean id="securityManager"class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm"ref="myShiro"/><property name="cacheManager"ref="cacheManager"/></bean><bean id="shiroFilter"class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager"ref="securityManager"/><property name="loginUrl"value="/login"/><property name="successUrl"value="/user"/><property name="unauthorizedUrl"value="/403"/><property name="filterChainDefinitions"><value><!--静态资源直接通过-->/static/** =anon<!--只有admin角色才能访问/user/save-->/user/save =roles[admin]<!--具有user:add权限的用户可以访问/user/save--><!--/user/save =perms[user:add]--><!--所有的请求都要通过验证-->/** = authc</value></property></bean><bean id="cacheManager"class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/><bean id="lifecycleBeanPostProcessor"class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/></beans>

 6.实现MyRealm:继承AuthorizingRealm,并重写认证授权方法 

package com.kaishengit.service;import java.util.List;import javax.inject.Inject;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.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import com.kaishengit.pojo.Role;import com.kaishengit.pojo.User;@Service@Transactionalpublic class MyRealm extends AuthorizingRealm{@Injectprivate UserService userService;/** * 权限认证*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {//获取登录的用户名String loginName=(String) principalCollection.fromRealm(getName()).iterator().next();User user=userService.findByName(loginName);if(user!=null){SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();//登录的用户有多少个角色info.setRoles(user.getRolesName());List<Role> roleList=user.getRoleList();for(Role role:roleList){//角色有多少个权限info.addStringPermissions(role.getPermissionNames());}return info;}return null;}/** * 登录认证*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;User user = userService.findByName(token.getUsername());if(user != null) {return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());}return null;}}

7.HomeController.java

package com.kaishengit.controller;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.UsernamePasswordToken;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.mvc.support.RedirectAttributes;import com.kaishengit.pojo.User;@Controllerpublic class HomeController {@RequestMapping(value="/login",method=RequestMethod.GET)public String loginForm(){return"/login";}@RequestMapping(value="/login",method=RequestMethod.POST)public String login(User user,RedirectAttributes redirectAttributes){try {SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));return"redirect:/user";} catch (AuthenticationException e) {redirectAttributes.addFlashAttribute("message","用户名或密码错误");return"redirect:/login";}}@RequestMapping(value="/logout",method=RequestMethod.GET)public String logout(RedirectAttributes redirectAttributes ){SecurityUtils.getSubject().logout();redirectAttributes.addFlashAttribute("message","您已安全退出");return"redirect:/login";}}

 8.在jsp中使用Shiro标签库:

<%@ taglib prefix="shiro"uri="http://shiro.apache.org/tags"%>

<html>

   <head>

      <title>page</title>

   </head>

   <body>

        <!--显示登录的用户名-->

        <h2>welcome!<shiro:principal/></h2>

  <a href="/logout">安全退出</a>

        <!--角色为manager的用户登录后会显示添加按钮,否则不显示-->

  <shiro:hasRole name="manager">

  <a href="/user/save">添加</a>

  </shiro:hasRole>                                                              

    </body>                                                    

</html>

9.数据库中建表,E-R图如下:

0 0
原创粉丝点击