1、创建maven-web项目
2、导入pomp文件。除了正常的项目依赖之外,Spring整合Shiro还需要另外导入3个依赖,如下。
<!--shiro核心包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.1</version>
</dependency>
<!--shiro的web包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.4.1</version>
</dependency>
<!--shiro和spring的整合包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
3、配置文件
①web.xml文件:配置Shiro过滤器:代理过滤器,还需要在Spring配置文件中配置具体的Bean对象来负责过滤,起到初次拦截用户url地址的作用;过滤客户端发送请求的url地址。
<!--加载applicationContext.xml,用于扫描springMvc,service,到等配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</context-param>
<!--Web项目需要指定监听器,若不配找不到bean对象,用于监听bean对象-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置分发器:DispatcherServlet-->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<!--服务器启动之后就初始化该Servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<!--
*.do/action:避免屏蔽访问静态文件
/:
1、访问不了静态资源文件
2、支持url地址的Restful风格 ?
/*:错误的写法 定位到jsp上,而不是找Controller
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--
Shiro过滤器:代理过滤器,还需要在配置文件中再次配置,初次拦截用户的url地址
过滤客户端发送的请求url地址
-->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!--设置成true:由Servlet容器管理过滤器的生命周期-->
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
<!--设置Spring容器的filter的bean的id,如果不设置,默认以filter-name的
值尾bean的id号-->
<init-param>
<param-name>targetBeanName</param-name>
<param-value>shiroFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--全站编码过滤器,解决post乱码,tomcat7.0以后的版本就不用考虑get乱码-->
<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>
<!--是否强制设置response的编码为encoding,建议设置为true-->
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
②spring-shiro.xml:这里我们使用自定义Realm实现数据源的管理
- web.xml中shiroFilter对应的bean:拦截地址
过滤器链用来拦截和放行请求,ShiroWeb中的所有功能,都是通过各种过滤器(拦截器)来完成的。
【ShiroWeb中的所有功能,都是通过发送请求来完成的】
- 配置权限管理器(SecurityManager):配置Realm
- 自定义Realm:配置凭证匹配器,为登录的密码加密服务
- 配置自定义登出过滤器:实现登出功能
<!--web.xml中shiroFilter对应的bean-->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
<!--权限管理器-->
<property name="securityManager" ref="securityManager" />
<!--认证url地址-->
<property name="loginUrl" value="/user/login"/>
<!--认证成功之后,跳转的地址-->
<property name="successUrl" value="/user/toIndex"/>
<!--配置表单认证过滤器-->
<property name="filters">
<map>
<!--将自定义的FormAuthenticationFileter注入shiroFilter中-->
<entry key="authc" value-ref="formAuthenticationFilter"/>
<!--自定义登出过滤器-->
<entry key="logout" value-ref="logOutFilter"/>
</map>
</property>
<!--没有权限操作跳转页面url地址-->
<!--<property name="unauthorizedUrl" value="/unauthorized"/>-->
<!--过滤器链定义,自上而下顺序执行,一般将/**放在最后-->
<property name="filterChainDefinitions">
<value>
<!--静态资源访问-->
/image/** = anon
/jquery/** = anon
/login.jsp = anon
/settings/user/logOut = logout
<!--/toSave = perms["role:add"]-->
/** = authc
</value>
</property>
</bean>
<!--配置自定义登出过滤器-->
<bean id="logOutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
<property name="redirectUrl" value="/login.jsp"/>
</bean>
<!--配置表单过滤器-->
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
<property name="usernameParam" value="loginAct"/>
<property name="passwordParam" value="loginPwd"/>
</bean>
<!--securityManager权限管理器-->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realms">
<list>
<ref bean="customRealm"/>
</list>
</property>
</bean>
<!--自定义realm-->
<bean id="customRealm" class="com.bjpowernode.shiro.realm.ShiroRealm">
<property name="credentialsMatcher" >
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--散列算法 加密算法类型MD5-->
<property name="hashAlgorithmName" value="md5"></property>
<!--散列次数 加密次数-->
<property name="hashIterations" value="1"></property>
</bean>
</property>
</bean>
配置缩写 |
对应的过滤器 |
功能 |
|
anon |
AnonymousFilter |
指定url可以匿名访问 |
|
authc |
FormAuthenticationFilter |
基于表单的拦截器;如“/**=authc”,如果没有登录会跳到相应的登录页面登录;主要属性:usernameParam:表单提交的用户名参数名( username); passwordParam:表单提交的密码参数名(password); rememberMeParam:表单提交的密码参数名(rememberMe); loginUrl:登录页面地址(/login.jsp);successUrl:登录成功后的默认重定向地址; failureKeyAttribute:登录失败后错误信息存储key(shiroLoginFailure) |
|
logout |
LogoutFilter |
退出拦截器,主要属性:redirectUrl:退出成功后重定向的地址(/) |
|
user |
UserFilter |
用户拦截器,用户已经身份验证/记住我登录的都可 |
|
perms |
PermissionsAuthorizationFilter |
角色授权拦截器,验证用户是否拥有所有角色;主要属性: loginUrl:登录页面地址(/login.jsp);unauthorizedUrl:未授权后重定向的地址;示例“/admin/**=roles[admin]” |
③springMVC:用于管理视图层
<!--开启AOP代理功能-->
<aop:config proxy-target-class="true" />
<!--开启shiro注解-->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<!--自定义异常-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--转发,默认按视图解析器进行页面跳转-->
<prop key="org.apache.shiro.authz.UnauthorizedException">/unauthorized</prop>
</props>
</property>
</bean>
<!--扫描Controller-->
<context:component-scan
base-package="com.bjpowernode.shiro.controller" />
<!--配置处理器适配器和处理器映射器-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!--json解析器-->
<bean id="mappingJacksonHttpMessageConverter"
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<!--class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">-->
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json</value>
<value>application/xml;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--处理静态资源文件-->
<mvc:default-servlet-handler />
<!--视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp"/>
</bean>
④spring-service:用于管理业务层
<!--导入dao.xml文件-->
<import resource="classpath:spring-dao.xml" />
<!--事务管理器:bean-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--配置AOP-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(*
com.bjpowernode.shiro..service.*.*(..))" />
<aop:advisor advice-ref="trAdvice" pointcut-ref="pointcut" />
</aop:config>
<!--配置的事物的传播特性-->
<tx:advice id="trAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="*bind*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="call*" propagation="REQUIRED" />
<tx:method name="convert*" propagation="REQUIRED" />
<tx:method name="*Stages*" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
⑤spring-dao:用于管理数据层
<!--配置数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--配置SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--Mybatis:扫描包,给定实体类别名,默认是类名首字母小写-->
<property name="typeAliasesPackage" value="com.bjpowernode.shiro.bean" />
<!--批量扫描映射文件-->
<property name="mapperLocations" value="classpath:mappers/*.xml" />
<!--导入SqlMapConfig.xml-->
<property name="configLocation" value="classpath:Mybatis/SqlMapConfig.xml" />
</bean>
<!--
扫描mapper接口,Spring框架给持久层接口创建代理子类
tk.mybatis.spring.mapper.MapperScannerConfigurer
既能使用传统的Mybatis,又能使用tkMapper
org.mybatis.spring.mapper.MapperScannerConfigurer
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bjpowernode.shiro.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
⑥spring-dao:用于扫描包,管理Bean对象
<!--引入db.properties-->
<context:property-placeholder location="classpath:Mybatis/db.properties"/>
<!--扫描包,管理Bean对象-->
<context:component-scan base-package="com.bjpowernode.shiro"/>
<import resource="classpath:spring-service.xml"/>