Eclipse中整合SSM+Maven+Shiro。 项目中有用到shiro,所以查了些资料搭建了个Demo,有兴趣的可以看看。
1.搭建完后项目结构
1.1 创建Maven项目
打包方式选war
2.配置文件
2.1 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.shiro.demo</groupId>
<artifactId>shiro-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>shiro-demo</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- shiro核心包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.5</version>
</dependency>
<!-- 添加shiro web支持 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.5</version>
</dependency>
<!-- 添加shiro spring支持 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.5</version>
</dependency>
<!-- 添加sevlet支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- 添加jsp支持 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 添加jstl支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- 添加log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<!-- 添加spring支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<!-- 添加mybatis支持 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.18</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.15</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>shiro</finalName>
</build>
</project>
- log4j.rootLogger=DEBUG, Console
- #Console
- log4j.appender.Console=org.apache.log4j.ConsoleAppender
- log4j.appender.Console.layout=org.apache.log4j.PatternLayout
- log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
- log4j.logger.java.sql.ResultSet=INFO
- log4j.logger.org.apache=INFO
- log4j.logger.java.sql.Connection=DEBUG
- log4j.logger.java.sql.Statement=DEBUG
- log4j.logger.java.sql.PreparedStatement=DEBUG
2.2.1 conf-db.properties
datasource.driverClassName=com.mysql.jdbc.Driver
datasource.timeBetweenEvictionRunsMillis=60000
datasource.minEvictableIdleTimeMillis=300000
datasource.validationQuery=SELECT 'x'
datasource.testWhileIdle=true
datasource.testOnBorrow=false
datasource.testOnReturn=false
datasource.url=jdbc:mysql://***.***.**.**:3306/**?useUnicode=true&characterEncoding=UTF-8
datasource.username=****
datasource.password=****
datasource.initialSize=3
datasource.minIdle=3
datasource.maxActive=20
datasource.maxWait=60000
2.3 web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
- <display-name>shiro-demo</display-name>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- <!-- spring监听器 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:applicationContext.xml</param-value>
- </context-param>
- <!-- 添加springmvc支持 -->
- <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:spring-mvc.xml</param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>springMVC</servlet-name>
- <url-pattern>*.do</url-pattern>
- </servlet-mapping>
- <!-- 添加shiro过滤器 -->
- <filter>
- <filter-name>shiroFilter</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- <init-param>
- <!-- 该值缺省为false,表示声明周期由SpringApplicationContext管理,设置为true表示ServletContainer管理 -->
- <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>
- <!-- 编码过滤器 -->
- <filter>
- <filter-name>encodingFilter</filter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
- <async-supported>true</async-supported>
- <init-param>
- <param-name>encoding</param-name>
- <param-value>UTF-8</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>encodingFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- </web-app>
- <?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:aop="http://www.springframework.org/schema/aop"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:jee="http://www.springframework.org/schema/jee"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
- http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
- <!-- 自动扫描 -->
- <context:component-scan base-package="com.demo.service" />
- <!-- 加载配置we -->
- <context:property-placeholder location="classpath*:conf*.properties"/>
- <!--配置数据源-->
-
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!--数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass --> <property name="driverClassName" value="${datasource.driverClassName}" /> <!--基本属性 url user password --> <property name="url" value="${datasource.url}" /> <property name="username" value="${datasource.username}" /> <property name="password" value="${datasource.password}" /> <!--配置初始化大小、最小、最大 --> <property name="initialSize" value="${datasource.initialSize}" /> <property name="minIdle" value="${datasource.minIdle}" /> <property name="maxActive" value="${datasource.maxActive}" /> <!--配置获取连接等待超时的时间 --> <property name="maxWait" value="${datasource.maxWait}" /> <!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${datasource.timeBetweenEvictionRunsMillis}" /> <!--配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${datasource.minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${datasource.validationQuery}" /> <property name="testWhileIdle" value="${datasource.testWhileIdle}" /> <property name="testOnBorrow" value="${datasource.testOnBorrow}" /> <property name="testOnReturn" value="${datasource.testOnReturn}" /> <!-- 配置监控统计拦截的filters --> <property name="filters" value="stat" /> </bean>
- <!--配置mybatis的sqlSessionFactory-->
- <bean name="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource"/>
- <!-- 自动扫描mappers.xml文件 -->
- <property name="mapperLocations" value="classpath:demo/mappers/*.xml "/>
- <!--mybatis配置文件-->
- <property name="configLocation" value="classpath:mybatis-config.xml"/>
- </bean>
- <!--DAO接口所在包名,spring 会自动查找其下的-->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.demo.dao"/>
- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
- </bean>
- <!--自定义Realm-->
- <bean id="myRealm" class="com.demo.realm.MyRealm"/>
- <!--安全管理-->
- <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
- <property name="realm" ref="myRealm"></property>
- </bean>
- <!--shiro 过滤器-->
- <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
- <!-- Shiro过滤器的核心安全接口,这个属性是必须的-->
- <property name="securityManager" ref="securityManager"/>
- <!--身份认证失败,则跳转到登录页面的配置-->
- <property name="loginUrl" value="/login.jsp"/>
- <!--权限认证失败,则跳转到指定页面-->
- <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
- <!-- Shiro连接约束配置,即过滤链的定义-->
- <property name="filterChainDefinitions">
- <value>
- /login=anon
- /user/admin*=authc
- /user/student*/**=roles[teacher]
- /user/teacher*/**=perms["user:create"]
- </value>
- </property>
- </bean>
- </beans>
3.整合Mybatis
3.1全局配置文件
首先配置一个mybatis的全局配置文件mybatis-config.xml,因为数据源都交给spring管理了,所以全局配置文件就比较清晰了。
mybatis-config.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>
- <!-- 别名 -->
- <typeAliases>
- <package name="com.demo.entity"/>
- </typeAliases>
- </configuration>
UserMapper.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.demo.entity.User">
- <select id="getByUsername" parameterType="String" resultType="user">
- select * from tb_user where username=#{username}
- </select>
- <select id="getRoles" parameterType="String" resultType="String">
- select r.rolename from t_user u,t_role r where u.role_id=r.id and u.username=#{username}
- </select>
- <select id="getPermissions" parameterType="String" resultType="String">
- select p.permissionname from t_user u,t_role r,t_permission p where u.role_id=r.id and p.role_id=r.id
- and u.username=#{username}
- </select>
- </mapper>
- public interface UserMapper {
- public User getByUsername(String username);
- public Set<String> getRoles(String username);
- public Set<String> getPermissions(String username);
- }
3.4 entity类
这里写个简单的User类
- public class User {
- private Integer id;
- private String username;
- private String password;
- //get set方法省略
- }
接口UserService.java
- public interface UserService {
- public User getByUsername(String username);
- public Set<String> getRoles(String username);
- public Set<String> getPermissions(String username);
- }
UserServiceImpl.Java
- @Service
- public class UserServiceImpl implements UserService {
- @Resource
- private UserMapper userDao;
- public User getByUsername(String username){
- return userDao.getByUsername(username);
- }
- public Set<String> getRoles(String username){
- return userDao.getRoles(username);
- }
- public Set<String> getPermissions(String username){
- return userDao.getPermissions(username);
- }
- }
4 整合SpringMVC
4.1配置文件
spring-mvc.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:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:jee="http://www.springframework.org/schema/jee"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
- http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
- <!-- 使用注解的包,包括子集-->
- <context:component-scan base-package="demo.controller"/>
- <!--视图解析器-->
- <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/"></property>
- <property name="suffix" value=".jsp"></property>
- </bean>
- </beans>
4.2 Controller
UserController.java
- package demo.controller;
- import demo.entity.User;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.UsernamePasswordToken;
- import org.apache.shiro.subject.Subject;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.stereotype.Controller;
- import javax.servlet.http.HttpServletRequest;
- @Controller
- @RequestMapping("/user")
- public class UserController {
- //用户登录
- @RequestMapping("/login")
- public String login(User user, HttpServletRequest request){
- Subject subject=SecurityUtils.getSubject();
- UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
- try {
- //调用subject.login(token)进行登录,会自动委托给securityManager,调用之前
- subject.login(token);//会跳到我们自定义的realm中
- request.getSession().setAttribute("user",user);
- return "success";
- }catch (Exception e){
- e.printStackTrace();
- request.getSession().setAttribute("user",user);
- request.setAttribute("error","用户名或密码错误");
- return "login";
- }
- }
- @RequestMapping("/logout")
- public String logout(HttpServletRequest request){
- request.getSession().invalidate();
- return "index";
- }
- @RequestMapping("/admin")
- public String admin(HttpServletRequest request){
- return "success";
- }
- @RequestMapping("/student")
- public String student(HttpServletRequest request){
- return "success";
- }
- @RequestMapping("/teacher")
- public String teacher(HttpServletRequest request){
- return "success";
- }
- }
上面用户登录会执行一个subject.login(token);这里会跳转到我们自定义的realm中,接下来就定义一下我们自己的realm,由于这里是和mybatis整合了,所以不需要原来的那个Dbutil去连接数据库了,直接使用mybatis中的mapper接口,也就是上面写的dao。
- public class MyRealm extends AuthorizingRealm {
- @Resource
- private UserServiceImpl userServiceImpl;
- //为当前登录成功的用户授予权限和角色,已经登录成功了。
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- String username=(String) principals.getPrimaryPrincipal();
- SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
- authorizationInfo.setRoles(userServiceImpl.getRoles(username));
- authorizationInfo.setStringPermissions(userServiceImpl.getPermissions(username));
- return authorizationInfo;
- }
- //验证当前登录的用户,获取认证信息。
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- String username=(String) token.getPrincipal();//获取用户名
- User user=userServiceImpl.getByUsername(username);
- if(user!=null){
- AuthenticationInfo authcInfo =new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),"myRealm");
- return authcInfo;
- }else{
- return null;
- }
- }
- }
login.jsp
- <body>
- <form action="${pageContext.request.contextPath }/user/login.do" method="post">
- username:<input type="text" name="username"/><br>
- password:<input type="password" name="password"/><br>
- <input type="submit" value="登录">${error}
- </form>
- </body>
success.jsp
- <body>
- 欢迎你${user.username}
- <a href="/user/logout.do">退出</a>
- </body>
unauthorized.jsp
- <body>
- 认证未通过,或者权限不足
- <a href="${pageContext.request.contextPath}/user/login.do">退出</a>
- </body>
6.测试
根据spring的配置文件中对shiro的url拦截配置,我们首先请求:http://localhost:8080/shiro-demo/user/admin.do来测试身份认证,然后会跳转到登录页面让我们登录,登录成功后,再次请求这个url就会进入success.jsp页面了。
再测试角色和权限认证,可以先后输入http://localhost:8080/shiro-demo/user/student.do来测试角色认证,输入http://localhost:8080/shiro-demo/user/teacher.do来测试权限认证。通过登陆不同的用户去测试即可。
参考这个博主的:http://blog.csdn.net/sanluo11/article/details/60581067