SSM项目与Shiro项目的整合(单体式项目)
Posted psy-code
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSM项目与Shiro项目的整合(单体式项目)相关的知识,希望对你有一定的参考价值。
1.项目的包结构:
2.jar包,配置文件及工具类
2.1pom.xml的配置
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zy</groupId> <artifactId>ssm-shiro</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>ssm-shiro Maven Webapp</name> <!-- FIXME change it to the project‘s website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> <shiro.version>1.2.3</shiro.version> <commons-logging.version>1.2</commons-logging.version> <!--spring家族版本号--> <spring.version>4.2.4.RELEASE</spring.version> <!--aop版本--> <org.aspectj.version>1.6.11</org.aspectj.version> <aopalliance.version>1.0</aopalliance.version> <!--数据源,mybatis,分页相关配置--> <druid.version>1.0.21</druid.version> <mybatis.version>3.2.6</mybatis.version> <mybatis.spring.version>1.3.1</mybatis.spring.version> <pageHelper.version>5.1.2</pageHelper.version> <mybatis-paginator.version>1.2.15</mybatis-paginator.version> <mysql.version>5.1.45</mysql.version> <!--jsp--> <jstl.version>1.2</jstl.version> <servlet.api>2.5</servlet.api> <jsp.api.version>2.0</jsp.api.version> <!--动态代理--> <cglib.version>2.1_3</cglib.version> <!--日志--> <org.slf4j.version>1.6.1</org.slf4j.version> <!--配置junit--> <junit.version>4.11</junit.version> <!--配置jackson的包--> <jackson.version>2.4.2</jackson.version> </properties> <dependencies> <!--配置jackson的包--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <!--配置shiro的依赖--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-quartz</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>${commons-logging.version}</version> </dependency> <!--配置spring核心包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <!--配置springMVC--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!--配置aop--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${org.aspectj.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${org.aspectj.version}</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>${aopalliance.version}</version> </dependency> <!--配置数据源,连接池,Mybatis,分页插件--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis.spring.version}</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pageHelper.version}</version> </dependency> <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artifactId> <version>${mybatis-paginator.version}</version> </dependency> <!--jsp相关--> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet.api}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.api.version}</version> <scope>provided</scope> </dependency> <!--动态代理--> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>${cglib.version}</version> </dependency> <!--配置日志--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${org.slf4j.version}</version> </dependency> </dependencies> <build> <finalName>ssm-shiro</finalName> <!--配置静态资源不发布--> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> </resources> <!--配置tomcat--> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <path>/</path> <port>8081</port> </configuration> </plugin> </plugins> </build> </project>
2.2配置springmvc.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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--开启自动扫包:注意这里只扫描controller层的包,防止重复扫描--> <context:component-scan base-package="com.zy.controller"/> <!--开启注解驱动:用来替换处理器适配器和处理器映射器--> <mvc:annotation-driven/> <!--视图解析器:配置返回的前缀及后缀--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean> <!--拦截静态资源并放行--> <mvc:default-servlet-handler /> <!--此处的mapping指代前台引用的地址,location指代资源实际地址--> <mvc:resources mapping="/js/**" location="/WEB-INF/js/"></mvc:resources> <mvc:resources mapping="/css/**" location="/WEB-INF/css/"></mvc:resources> <mvc:resources mapping="/fonts/**" location="/WEB-INF/fonts/"></mvc:resources> <mvc:resources mapping="/images/**" location="/WEB-INF/images/"></mvc:resources> <mvc:resources mapping="/layui/**" location="/WEB-INF/layui/"></mvc:resources> <!--开启aop注解支持--> <aop:config proxy-target-class="true"/> <!--开启全局异常处理--> <bean class="com.zy.common.MyExceptionHandler"/> </beans>
2.3配置spring相关内容
2.3.1配置applicationContext-dao.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:mybatis-spring="http://mybatis.org/schema/mybatis-spring" 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://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd"> <!--1.配置自动扫描:注意这里只扫描dao层和service层的包,不扫描controller,防止与springmvc重复扫描--> <context:component-scan base-package="com.zy.mapper"/> <!--2.读取配置文件--> <context:property-placeholder location="classpath:db.properties"/> <!--3.配置数据库连接的基本情况--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!--3.1数据库连接的基本属性的设置--> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="driverClassName" value="${jdbc.driver}"/> <!--3.2配置最大最小值以及初始化的值--> <property name="initialSize" value="1"/> <property name="minIdle" value="1"/> <property name="maxActive" value="10"/> </bean> <!--4.配置dao层,整合Mybatis--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--配置Mybatis的全局配置文件--> <property name="configLocation" value="classpath:mybatis/sqlMappingConfig.xml"/> <!--mapperLocations: 指定mapper文件的位置--> <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/> </bean> <!--4.1也可以扫描与mapper层同级目录的文件配置 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.zy.mapper"/> </bean> --> <!-- 扫描所有的mapper接口的实现,让这些mapper能够自动注入; base-package:指定mapper接口的包名 --> <mybatis-spring:scan base-package="com.zy.mapper"/> </beans>
2.3.2配置applicationContext-service.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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.zy.service"/> </beans>
2.3.3配置applicationContext-tx.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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--5.添加事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!--6.基于XML的事务--> <tx:advice transaction-manager="transactionManager" id="transactionInterceptor"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="modify*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="query*" propagation="SUPPORTS"/> <tx:method name="get*" propagation="SUPPORTS"/> <tx:method name="find*" propagation="SUPPORTS"/> <tx:method name="select*" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!--配置切入点--> <aop:config> <aop:pointcut id="serviceAdvice" expression="execution(* com.zy.service..* .*(..))"></aop:pointcut> <!--将事务织入切入对象中--> <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="serviceAdvice"/> </aop:config> </beans>
2.3.4配置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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--申明缓存管理器--> <!--本地缓存,不推荐--> <!--<bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/>--> <!-- 缓存管理器使用Ehcache实现 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:ehcache.xml" /> </bean> <!--密码凭证管理器--> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="md5"/> <!--次数--> <property name="hashIterations" value="1"/> </bean> <!--================================配置自定义的realm====================================--> <bean id="tbUserRealm" class="com.zy.shiro.TbUserRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"/> <!--配置缓存时,改为true--> <property name="cachingEnabled" value="true"/> </bean> <!--记住我的cookie--> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe"/> <!--设置cookie有效期--> <property name="maxAge" value="604800"/> </bean> <!--记住我管理器--> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="rememberMeCookie"/> </bean> <!--安全管理器--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="tbUserRealm"/> <!--注入记住我--> <property name="rememberMeManager" ref="rememberMeManager"/> <!--缓存管理器--> <property name="cacheManager" ref="cacheManager"/> </bean> <!--=====================开启切面支持,spring拦截支持=====================--> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <!--调用securityManagerUtils.setSecurityManager--> <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/login"/> <property name="successUrl" value="/login/loginCheck"/> <property name="filterChainDefinitions"> <value> <!-- anon:匿名使用,用户不登录也可以访问,如 /item/** = anon authc:认证后才能使用 /order/** = authc roles:需要特定角色才能访问 /admin/** = roles["admin,test"] perms:需要特定权限才能访问 /admin/user/** = perms["user:add,user:delete"] user:必须存在用户,登录而不限制检查 /** = user rest: restFul风格 /adimn/** = rest[user] port: 限制访问端口 /admin/** = port[8088] authcBasic: 限制协议请求是https ssl: 安全的url请求,请求协议是http --> <!--切记此处路径名与前台传.递的路径名是一致的,除了在此处配置以外,还需要在spring.xml中进行配置--> /css/** = anon<!--设置静态资源文件为游客可访问--> /js/** = anon<!--设置静态资源文件为游客可访问--> /fonts/** = anon<!--设置静态资源文件为游客可访问--> /images/** = anon<!--设置静态资源文件为游客可访问--> /layui/** = anon<!--设置静态资源文件为游客可访问--> <!--配置用户退出 不用我们去实现退出,只要去访问一个退出的url(该 url是可以不存在),由LogoutFilter拦截住,清除session。 在applicationContext-shiro.xml配置LogoutFilter --> /login/logout = logout <!--不拦截--> /login/** = anon /** = user </value> </property> </bean> <!--生命周期的配置--> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> </beans>
2.4配置mybatis相关内容
2.4.1配置sqlMappingConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--设置全局配置环境--> <settings> <!--开启全局缓存--> <setting name="cacheEnabled" value="true"/> <!--开启懒加载--> <setting name="lazyLoadingEnabled" value="true"/> <!--关闭延迟加载--> <setting name="aggressiveLazyLoading" value="false"/> </settings> <!--配置分页插件pageHelper的拦截器:5.0版本之后的配置--> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins> </configuration>
2.4.2配置其他***Mappper.xml文件(以TbUserMapper.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="com.zy.mapper.TbUserMapper"> <!--封装结果集--> <resultMap id="tbUserResultMap" type="com.zy.model.TbUser"> <id column="id" property="id" jdbcType="INTEGER"/> <result column="username" property="username" jdbcType="VARCHAR"/> <result column="password" property="password" jdbcType="VARCHAR"/> <result column="salt" property="salt" jdbcType="VARCHAR"/> <result column="status" property="status" jdbcType="VARCHAR"/> </resultMap> <!-- 根据用户名查询用户信息 TbUser getTbUserByUserName(String username); --> <select id="getTbUserByUserName" resultMap="tbUserResultMap"> select id,username,password,salt,status from tb_user where username = #{username} </select> <!-- // 注册用户 int addTbUser(TbUser tbUser); --> <insert id="addTbUser"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select last_insert_id() </selectKey> insert into tb_user values(null,#{username},#{password},#{salt},#{status}) </insert> <!-- // 查询所有用户信息 List<TbUser> getAllUser(); --> <select id="getAllUser" resultMap="tbUserResultMap"> select id,username,password,salt,status from tb_user </select> <!-- // 删除用户信息及其关联角色信息,还需要去关联表中删除该信息 void deleteUser(Integer id); --> <delete id="deleteUser"> delete from tb_user where id = #{id} </delete> <delete id="deleteUserRole"> delete from tb_user_role where user_id = #{id} </delete> </mapper>
2.5配置db.properties
####配置mysql的连接 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/shiro jdbc.username=root jdbc.password=123456 ####配置oracle的连接 orcl.driver=oracle.jdbc.OracleDriver orcl.url=jdbc:oracle:thin:@localhost:1521:orcl orcl.username=tom orcl.password=123456
2.6配置ehcache.xml
<?xml version="1.1" encoding="UTF-8"?> <ehcache updateCheck="false" name="shirocache"> <diskStore path="D:developehcache" /> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
2.7配置log4j.properties
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=/scheduler.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change ‘info‘ to ‘debug‘ ### log4j.rootLogger=debug,stdout,file
2.8mapper层,以TbUserMapper为例
package com.zy.mapper; import com.zy.model.TbUser; import org.springframework.stereotype.Repository; /** * 用户信息的Mapper */ import java.util.List; /** * Created by Administrator on 2018/7/3. * * 用户登录的mapper */ @Repository public interface TbUserMapper { // 根据用户名查询用户信息 TbUser getTbUserByUserName(String username); // 注册用户 int addTbUser(TbUser tbUser); // 查询所有用户信息 List<TbUser> getAllUser(); // 删除用户信息及其关联角色信息 void deleteUser(Integer id); void deleteUserRole(Integer id); }
2.9service层(以TbUserServiceI和TbUserServiceImpl为例)
package com.zy.service; import com.zy.model.TbPermission; import com.zy.model.TbRole; import com.zy.model.TbUser; import com.zy.util.PageUtils; import java.util.List; import java.util.Map; /** * Created by Administrator on 2018/7/3. */ public interface TbUserServiceI { // 登录验证:根据用户名查询用户信息 TbUser getTbUserByUserName(String username); // 授权验证第一步:根据用户id查询用户角色 List<TbRole> getTbRoleByUserId(Integer id); // 授权验证:根据用户id查询用户权限信息 List<TbPermission> getTbPermissionByUserId(Integer userId); // 查询菜单信息 Map<TbPermission, List<TbPermission>> getMenuByUserId(Integer userId); // 注册用户 int addTbUser(TbUser tbUser); // 查询所有用户信息 PageUtils getAllUser(Integer pageNo); // 删除用户信息及其关联角色信息 void deleteUser(Integer id); }
package com.zy.service.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.zy.common.ConstantValue; import com.zy.mapper.TbPermissionMapper; import com.zy.mapper.TbRoleMapper; import com.zy.mapper.TbUserMapper; import com.zy.model.TbPermission; import com.zy.model.TbRole; import com.zy.model.TbUser; import com.zy.service.TbUserServiceI; import com.zy.util.MD5; import com.zy.util.PageUtils; import org.apache.shiro.crypto.SecureRandomNumberGenerator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by Administrator on 2018/7/3. * * 登录的业务层 */ @Service("tbUserService") public class TbUserServiceImpl implements TbUserServiceI { @Autowired private TbUserMapper tbUserMapper; @Autowired private TbRoleMapper tbRoleMapper; @Autowired private TbPermissionMapper tbPermissionMapper; // 登录验证:根据用户名查询用户信息 @Override public TbUser getTbUserByUserName(String username) { TbUser tbUser = tbUserMapper.getTbUserByUserName(username); return tbUser; } // 授权验证第一步:根据用户id查询用户角色 @Override public List<TbRole> getTbRoleByUserId(Integer id) { List<TbRole> tbRoleList = tbRoleMapper.getTbRoleByUserId(id); return tbRoleList; } // 授权验证:根据用户id查询用户权限信息 @Override public List<TbPermission> getTbPermissionByUserId(Integer userId) { List<TbPermission> permissionList = tbPermissionMapper.getTbPermissionByUserId(userId); return permissionList; } // 查询菜单信息 @Override public Map<TbPermission, List<TbPermission>> getMenuByUserId(Integer userId){ List<TbPermission> permissionList = tbPermissionMapper.getTopTbPermissionByUserId(userId); Map<TbPermission, List<TbPermission>> map = new HashMap<TbPermission, List<TbPermission>>(); for(TbPermission tbPermission : permissionList){ if(tbPermission.getParentId() == null){ // 当用户id是确定的时候,根据父菜单id查询子菜单id List<TbPermission> list = tbPermissionMapper.getTbPermissionByParentIdAndUserId(tbPermission.getId(),userId); if(list != null){ map.put(tbPermission,list); } } } return map; } // 注册用户 @Override public int addTbUser(TbUser tbUser) { // 获取salt String salt=new SecureRandomNumberGenerator().nextBytes().toHex(); tbUser.setSalt(salt); // 进行加密 String md5Pwd = MD5.getMD5(tbUser.getPassword(), salt); tbUser.setPassword(md5Pwd); // 设置状态 tbUser.setStatus(ConstantValue.USER_STATUS_UNLOCKED); tbUserMapper.addTbUser(tbUser); /*返回主键*/ Integer id = tbUser.getId(); return id; } // 查询所有用户信息 @Override public PageUtils getAllUser(Integer pageNo) { PageHelper.startPage(pageNo, ConstantValue.PAGE_SIZE); List<TbUser> userList = tbUserMapper.getAllUser(); PageUtils pageInfo = new PageUtils(); pageInfo.setRows(userList); PageInfo<TbUser> pageInfoList = new PageInfo<TbUser>(userList); pageInfo.setTotalPages(pageInfoList.getPages()); pageInfo.setCurrentPage(pageNo); pageInfo.setPageSize(pageInfoList.getPageSize()); return pageInfo; } // 删除用户信息及其关联角色信息 @Override public void deleteUser(Integer id) { tbUserMapper.deleteUser(id); tbUserMapper.deleteUserRole(id); } }
2.10权限Realm(以TbUserRealm 为例)
package com.zy.shiro; import com.zy.common.ConstantValue; import com.zy.model.TbPermission; import com.zy.model.TbRole; import com.zy.model.TbUser; import com.zy.service.TbUserServiceI; import com.zy.util.MD5; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.authz.UnauthorizedException; 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 java.util.HashSet; import java.util.List; import java.util.Set; /** * Created by Administrator on 2018/7/2. * * 认证及授权的realm */ public class TbUserRealm extends AuthorizingRealm { @Autowired private TbUserServiceI tbUserService; /* * * 认证 * */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { /*获取输入的用户名及密码*/ String username = (String) token.getPrincipal(); String password = new String((char[]) token.getCredentials()); /*调用service层方法返回用户信息*/ TbUser tbUser = tbUserService.getTbUserByUserName(username); /*如果用户信息为Null,则抛出用户不存在异常*/ if(tbUser == null){ throw new UnknownAccountException("用户名为空-----------------"); } /*如果用户状态为1,则抛出账户锁定异常*/ if(tbUser.getStatus().equals(ConstantValue.USER_STATUS_LOCKED)){ throw new LockedAccountException("账号被锁定-----------------------"); } /*比较密码是否一致,如果不一致,则抛出密码错误异常*/ final String md5Password = MD5.getMD5(password, tbUser.getSalt()); if(!md5Password.equals(tbUser.getPassword())){ throw new IncorrectCredentialsException("密码错误---------------------"); } /*如果一切顺利,则返回该信息*/ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo( tbUser, md5Password, ByteSource.Util.bytes(tbUser.getSalt()), this.getName()); return info; } /* * * 授权 * * */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //从principals获取主身份信息 //将getPrimaryPrincipal方法返回值转为真实身份类型 //在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型 TbUser tbUser = (TbUser) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); if(tbUser != null){ //根据身份信息获取角色信息并且设置到PrincipalCollection中 List<TbRole> roleList = tbUserService.getTbRoleByUserId(tbUser.getId()); Set<String> roles = new HashSet<String>(); if(roleList != null){ for(TbRole tbRole : roleList){ if(tbRole.getRoleName() != null && !tbRole.getRoleName().equals("")){ roles.add(tbRole.getRoleName()); } } info.setRoles(roles); } //根据身份信息获取权限信息并且设置到PrincipalCollection中 List<TbPermission> permissionList = tbUserService.getTbPermissionByUserId(tbUser.getId()); if(permissionList != null){ Set<String> permissions = new HashSet<String>(); for(TbPermission tbPermission : permissionList){ if(tbPermission.getPerCode() != null && !tbPermission.getPerCode().trim().equals("")){ permissions.add(tbPermission.getPerCode()); } } info.setStringPermissions(permissions); } else{ throw new UnauthorizedException(); } } return info; } }
2.11controller层(以LoginController 为例)
package com.zy.controller; import com.zy.common.ConstantValue; import com.zy.model.TbPermission; import com.zy.model.TbUser; import com.zy.service.TbUserServiceI; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; 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.bind.annotation.ResponseBody; import javax.servlet.http.HttpSession; import java.util.List; import java.util.Map; /** * Created by Administrator on 2018/7/3. * <p> * 登录注册相关的controller */ @Controller @RequestMapping("login") public class LoginController { @Autowired private TbUserServiceI tbUserService; // 登录界面 @RequestMapping("login") public String login() { return "login/login"; } // 登录验证 @RequestMapping("loginCheck") public String loginCheck(TbUser tbUser, String rememberMe,Map map) { UsernamePasswordToken token = new UsernamePasswordToken(tbUser.getUsername(), tbUser.getPassword()); Subject subject = SecurityUtils.getSubject(); if (rememberMe == null) { token.setRememberMe(false); } else { token.setRememberMe(true); } try { subject.login(token); return "forward:toIndex"; } catch (Exception e) { map.put("msg","用户名或密码错误"); return "login/login"; } } // 如果登录成功,则跳转到此处,由此处获取信息,并发送至前台页面 @RequestMapping("toIndex") public String toIndex(Map map){ /*获取TbUserRealm中的Subject*/ final Subject subject = SecurityUtils.getSubject(); TbUser tbUser = (TbUser) subject.getPrincipal(); if(tbUser == null){ return "redirect:/login/login"; } /*将用户信息放到map中*/ map.put("tbUser", tbUser); /*查询菜单信息,并将菜单信息放置到map中*/ Map<TbPermission, List<TbPermission>> menu = tbUserService.getMenuByUserId(tbUser.getId()); map.put("menu",menu); return "index"; } /*注册*/ /*注册前用户名查重*/ @RequestMapping("isUserExist") @ResponseBody public String isUserExist(String username) { TbUser tbUser = tbUserService.getTbUserByUserName(username); if (tbUser == null) { return ConstantValue.USER_IS_NOT_EXIST; } return ConstantValue.USER_IS_EXIST; } @RequestMapping("register") public String register(String username, String password) { /*用户注册*/ TbUser tbUser = new TbUser(); tbUser.setUsername(username); tbUser.setPassword(password); tbUserService.addTbUser(tbUser); /*用户注册后,登录到首页展示页面*/ return "forward:loginCheck"; } /*用户退出登录*/ @RequestMapping("logout") public String logout(HttpSession session){ /*清除缓存*/ session.invalidate(); return "redirect:/login/login"; } }
2.12model层(以TBUser为例)
package com.zy.model; import java.io.Serializable; /** * * 定义用户登录表中的实体类 * Created by Administrator on 2018/7/3. */ public class TbUser implements Serializable { private Integer id; private String username; private String password; private String salt; private String status; @Override public String toString() { return "TbUser{" + "id=" + id + ", username=‘" + username + ‘‘‘ + ", password=‘" + password + ‘‘‘ + ", salt=‘" + salt + ‘‘‘ + ", status=‘" + status + ‘‘‘ + ‘}‘; } public Integer getId() { return id; } public void setId(Integer 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 String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public TbUser() { } public TbUser(Integer id, String username, String password, String salt, String status) { this.id = id; this.username = username; this.password = password; this.salt = salt; this.status = status; } }
2.13webapp下的web.xml配置
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>ssmshiro</display-name> <!--配置spring--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext-*.xml</param-value> </context-param> <!--配置乱码过滤器--> <filter> <filter-name>CharacterFilter</filter-name> <filter-class>com.zy.util.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <!--配置shiro拦截--> <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>CharacterFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置spring--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--配置springmvc--> <servlet> <servlet-name>Dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc/springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--配置欢迎界面--> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!--配置404和500--> <error-page> <error-code>404</error-code> <location>/WEB-INF/error/404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/WEB-INF/error/500.jsp</location> </error-page> </web-app>
以上是关于SSM项目与Shiro项目的整合(单体式项目)的主要内容,如果未能解决你的问题,请参考以下文章
008-shiro与spring web项目整合认证授权session管理