这几天在网上找了一些shiro相关的文章看了看,结合自己的理解写一篇文章以加深印象并希望能帮助初学者更好的使用shiro框架,老鸟请忽略~~
shiro的相关概念什么的我就不多说了,大家可以自己在网上找找,都是一样的话,我这里就不复制了,直接开始吧!
shiroDemo.rar项目下载地址
数据库准备三张表:t_user用户表,t_role角色表,t_permission权限表
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rolename` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `t_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`permission_name` varchar(255) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
//分别向三张表中插入数据
INSERT INTO `t_permission` VALUES ('1', 'user:create', '1');
INSERT INTO `t_permission` VALUES ('2', 'student:*', '2');
INSERT INTO `t_permission` VALUES ('3', 'student:*', '1');
INSERT INTO `t_role` VALUES ('1', 'admin');
INSERT INTO `t_role` VALUES ('2', 'teacher');
INSERT INTO `t_user` VALUES ('1', 'yangqing', '123', '1');
INSERT INTO `t_user` VALUES ('2', 'jack', '1', '2');
INSERT INTO `t_user` VALUES ('3', 'marry', '234', null);
INSERT INTO `t_user` VALUES ('4', 'json', '1234', null);
INSERT INTO t_role VALUES (‘1’, ‘admin’);
INSERT INTO t_role VALUES (‘2’, ‘teacher’);
INSERT INTO t_user VALUES (‘1’, ‘yangqing’, ‘123’, ‘1’);
INSERT INTO t_user VALUES (‘2’, ‘jack’, ‘1’, ‘2’);
INSERT INTO t_user VALUES (‘3’, ‘marry’, ‘234’, null);
INSERT INTO t_user VALUES (‘4’, ‘json’, ‘1234’, null);
配置文件
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.0modelVersion>
<groupId>com.yanggroupId>
<artifactId>shiroDemoartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>3.8.1version>
<scope>testscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.1version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>4.1.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>1.2.3version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.3.0version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.37version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>1.2.4version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.12version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-webartifactId>
<version>1.2.4version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.2.4version>
dependency>
dependencies>
project>
web.xml
<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_2_5.xsd"
id="WebApp_ID" version="2.5">
<filter>
<filter-name>shiroFilterfilter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
<init-param>
<param-name>targetFilterLifecycleparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>shiroFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<filter>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<async-supported>trueasync-supported>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<servlet>
<servlet-name>springMVCservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring-mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
<async-supported>trueasync-supported>
servlet>
<servlet-mapping>
<servlet-name>springMVCservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
applicationContext.xml
<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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:property-placeholder location="classpath:db.properties"/>
<context:component-scan base-package="com.yang.service" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}">property>
<property name="driverClass" value="${jdbc.driverClass}">property>
<property name="user" value="${jdbc.user}">property>
<property name="password" value="${jdbc.password}">property>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mapper/*.xml">property>
<property name="configLocation" value="classpath:mybatis-config.xml">property>
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.yang.dao" />
bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
bean>
<bean id="myRealm" class="com.yang.realm.MyRealm"/>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<property name="filterChainDefinitions">
<value>
/login=anon
/logout=logout
/admin=authc
/student=roles[teacher]
/teacher=perms["user:create"]
/**=authc
value>
property>
bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="new*" propagation="REQUIRED" />
<tx:method name="set*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="change*" propagation="REQUIRED" />
<tx:method name="check*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="txPoint"
expression="execution(* com.yang.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint" />
aop:config>
beans>
db.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/db_shiro?characterEncoding=utf8
jdbc.user=root
jdbc.password=root
log4j.properties
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
mybatis-config.xml
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<typeAliases>
<package name="com.yang.entity"/>
typeAliases>
configuration>
spring-mvc.xml
<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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.yang.controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/">property>
<property name="suffix" value=".jsp">property>
bean>
beans>
实体类
User.java
package com.yang.entity;
/**
* created by yangqing on 2018年2月19日 下午9:27:56
*/
public class User {
private Integer id;
private String username;
private String password;
private Integer roleId;
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 Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
}
dao接口
UserDao.java
package com.yang.dao;
import java.util.Set;
import com.yang.entity.User;
/**
* created by yangqing on 2018年2月19日 下午9:32:29
*/
public interface UserDao {
/**
* 通过用户名查找用户
* @param username
* @return User
*/
public User getByUserName(String username);
/**
* 通过用户名查找该用户所有的角色并保存在Set集合中
* @param username
* @return Set
*/
public Set<String> getRoles(String username);
/**
* 通过用户名查找该用户所有的权限并保存在Set集合中
* @param username
* @return Set
*/
public Set<String> getPermissions(String username);
}
UserDao接口的实现
UserMapper.xml (该文件在src/main/resources/mapper文件夹下)
<mapper namespace="com.yang.dao.UserDao">
<select id="getByUserName" parameterType="String" resultType="User">
select * from t_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.permission_name 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>
服务层
UserService.java
package com.yang.service;
import java.util.Set;
import com.yang.entity.User;
/**
*
* created by yangqing on 2018年2月19日 下午9:44:23
*/
public interface UserService {
/**
* 通过用户名查找用户
* @param username
* @return User
*/
public User getByUserName(String username);
/**
* 通过用户名查找该用户所有的角色并保存在Set集合中
* @param username
* @return Set
*/
public Set<String> getRoles(String username);
/**
* 通过用户名查找该用户所有的权限并保存在Set集合中
* @param username
* @return Set
*/
public Set<String> getPermissions(String username);
}
/**
* 通过用户名查找用户
* @param username
* @return User
*/
public User getByUserName(String username);
/**
* 通过用户名查找该用户所有的角色并保存在Set集合中
* @param username
* @return Set
*/
public Set<String> getRoles(String username);
/**
* 通过用户名查找该用户所有的权限并保存在Set集合中
* @param username
* @return Set
*/
public Set<String> getPermissions(String username);
}
UserServiceImpl.java
package com.yang.service.impl;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yang.dao.UserDao;
import com.yang.entity.User;
import com.yang.service.UserService;
/**
* created by yangqing on 2018年2月19日 下午9:45:51
*/
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDao 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);
}
}
Controller层
UserController.java
package com.yang.controller;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.yang.entity.User;
/**
*
* created by yangqing on 2018年2月19日 下午9:48:55
*/
@Controller
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);
request.setAttribute("user", user);
return "success";
}catch(Exception e){
e.printStackTrace();
request.setAttribute("user", user);
request.setAttribute("errorMsg", "用户名或密码错误!");
return "login";
}
}
@RequestMapping("/teacher")
public String index() {
return "index";
}
}
自定义realm
MyRealm.java
package com.yang.realm;
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.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 com.yang.entity.User;
import com.yang.service.UserService;
/**
* created by yangqing on 2018年2月19日 下午9:57:09
*/
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授权方法
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
/**
* 注意principals.getPrimaryPrincipal()对应
* new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(), getName())的第一个参数
*/
//获取当前身份
String userName = (String) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//从数据库中查找该用户有何角色和权限
Set<String> roles = userService.getRoles(userName);
Set<String> permissions = userService.getPermissions(userName);
//为当前用户赋予对应角色和权限
info.setRoles(roles);
info.setStringPermissions(permissions);
return info;
}
/**
* 认证方法
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户名
String username = (String) token.getPrincipal();
//从数据库中查找用户信息
User user = userService.getByUserName(username);
if (user == null) {
return null;
}
AuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
return info;
}
}
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录页面title>
head>
<body>
<form action="${pageContext.request.contextPath }/login" method="post">
用户名:<input type="text" name="username" value="${user.username }"/><br/>
密码:<input type="password" name="password" value="${user.password }"><br/>
<input type="submit" value="login"/><br>
<font color="red">${errorMsg }font>
form>
body>
html>
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功title>
head>
<body>
欢迎你,<shiro:principal/>!<br>
<shiro:hasRole name="admin">
具备admin角色才能看到这句话<br>
shiro:hasRole>
<shiro:hasRole name="teacher">
具备teacher角色才能看到这句话<br>
shiro:hasRole>
<shiro:hasPermission name="user:create">
具备user:create权限才能看到这句话<br>
shiro:hasPermission>
<shiro:hasPermission name="student:update">
具备student:update权限才能看到这句话<br>
shiro:hasPermission>
<br>
<shiro:hasPermission name="{student:update,user:*}">
具备student:update,user:*权限才能看到这句话<br>
shiro:hasPermission>
<a href="teacher">需要user:create权限才能访问a><br>
<a href="logout">安全退出a>
body>
html>
分别使用用户名为yangqing和jack的账号登录,测试如下:
tip:如果未登录(未通过认证)在地址栏输入http://localhost:8080/shiroDemo/success.jsp默认跳回login.jsp页面(被shiro拦截了,具体请参考上述配置文件 /**=authc部分)
错误用户试验
使用yangqing登录成功之后的页面
点击 需要user:create权限才能访问 链接之后的页面
使用jack登录成功之后的页面
jack用户 点击 需要user:create权限才能访问 链接之后的页面
小结:好累,眼睛疼,第一次写博客文章,本人也是菜鸟,正在一步一步往上爬,请大家多多指教,写的应该还算详细吧,大佬请手下留情,我还是个新手。。已经凌晨1点多了,肩膀好酸,我先睡了,晚安!