以下内容是在看了涛哥的《跟我一起学shiro》 和 视频《一头扎入进shiro》 后整理出来备忘和方便自己和其他人学习。
之前是在shiro.ini文件中配置用户和权限,现在要从数据库中读取,采用的是jdbc读取mysql数据库。
了解jdbc是如何读取mysql数据库:http://blog.csdn.net/qq_19558705/article/details/49947317
配合上一章内容Servlet代码:http://blog.csdn.net/qq_19558705/article/details/50775223
第一步:创建表
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`permissionName` varchar(50) DEFAULT NULL,
`roleId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `roleId` (`roleId`),
CONSTRAINT `t_permission_ibfk_1` FOREIGN KEY (`roleId`) REFERENCES `t_role` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `t_permission` VALUES ('1', 'user:*', '1');
INSERT INTO `t_permission` VALUES ('2', 'student:*', '2');
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`roleName` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `t_role` VALUES ('1', 'admin');
INSERT INTO `t_role` VALUES ('2', 'teacher');
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(20) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
`roleId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `roleId` (`roleId`),
CONSTRAINT `t_user_ibfk_1` FOREIGN KEY (`roleId`) REFERENCES `t_role` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
INSERT INTO `t_user` VALUES ('1', 'ITDragon', '123456', '1');
INSERT INTO `t_user` VALUES ('2', 'blog', '123456', '2');
第二步:连接数据库
添加java-mysql驱动:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.17</version>
</dependency>
连接数据库代码:
package com.shiro.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* 数据库连接类
* @author ITDragon
*
*/
public class ConnectionUtil {
/**
* 第一步:加载驱动
* 第二步:链接数据库
* 第三步:一定要关闭流
* 第四步:测试是否连接成功
*/
private static String DRIVER = "com.mysql.jdbc.Driver"; // 数据库驱动
private static String URL = "jdbc:mysql://localhost:3306/db_shiro"; // 访问数据库路径
private static String NAME = "root"; // 数据库用户名
private static String PASSWORD = "root"; // 数据库密码
public static Connection getConnection() {
Connection connection = null;
try {
// 加载驱动
Class.forName(DRIVER);
// 连接数据库
connection = DriverManager.getConnection(URL, NAME, PASSWORD);
return connection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// 关闭流
public static void closeConnection(Connection connection) {
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void closeStatement(Statement statement) {
try {
statement.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void closePreparedStatement(PreparedStatement pStatement) {
try {
pStatement.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void closeResultSet(ResultSet rs) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 测试数据库是否链接成功
public static void main(String[] args) {
System.out.println(getConnection());
}
}
第三步:自定义realm
首先准备一个用户的实体类
package com.shiro.entity;
public class User {
private Integer id;
private String userName;
private String password;
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;
}
}
准备一个查询用户信息,角色,权限的Dao
package com.shiro.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import com.shiro.entity.User;
public class UserDao {
// 通过用户名获取用户信息
public User getByUserName(Connection connection, String userName) {
User resultUser = null;
String sql = "select * from t_user where userName = ?";
PreparedStatement pstmt;
try {
pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userName);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
resultUser = new User();
resultUser.setId(rs.getInt("id"));
resultUser.setUserName(rs.getString("userName"));
resultUser.setPassword(rs.getString("password"));
}
return resultUser;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
// 通过用户名查询用户角色
public Set<String> getUserRoles(Connection connection, String userName) {
Set<String> roles = new HashSet<String>();
String sql = "select * from t_user u,t_role r where u.roleId=r.id and u.userName = ?";
PreparedStatement pstmt;
try {
pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userName);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
roles.add(rs.getString("roleName"));
}
return roles;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
// 通过用户名查询用户权限
public Set<String> getUserPermissions(Connection connection, String userName) {
Set<String> permissions = new HashSet<String>();
String sql = "select * from t_user u,t_role r,t_permission p "
+ "where u.roleId = r.id and p.roleId = r.id and u.userName = ?";
PreparedStatement pstmt;
try {
pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userName);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
permissions.add(rs.getString("permissionName"));
}
return permissions;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
自定义realm:
package com.shiro.realm;
import java.sql.Connection;
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 com.shiro.dao.UserDao;
import com.shiro.entity.User;
import com.shiro.utils.ConnectionUtil;
/**
* 自定义realm
* 步骤:
* s1:继承 AuthorizingRealm 并实现其方法
* s2:验证当前用户
* s3:给当前登录成功的用户授予角色和权限
* @author ITDragon
*
*/
public class MyRealm extends AuthorizingRealm{
private UserDao userDao = new UserDao();
// 给当前登录成功的用户授予角色和权限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
// 获取用户名
String userName = (String) principals.getPrimaryPrincipal();
// 认证信息
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
Connection connection = null;
try{
connection = ConnectionUtil.getConnection();
// 设置角色
simpleAuthorizationInfo.setRoles(userDao.getUserRoles(connection , userName));
// 设置权限
simpleAuthorizationInfo.setStringPermissions(userDao.getUserPermissions(connection , userName));
}catch(Exception e){
e.printStackTrace();
}finally{
try {
ConnectionUtil.closeConnection(connection);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
// 验证当前用户
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
// 获取用户信息
String userName = (String) token.getPrincipal();
Connection connection = null;
try{
connection = ConnectionUtil.getConnection();
// 通过用户名找到用户
User user = userDao.getByUserName(connection, userName);
if(null != user){
// 三个参数分别是: 用户名 , 密码 , rememberMe
AuthenticationInfo authcInfo =
new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"false");
return authcInfo;
}else{
return null;
}
}catch(Exception e){
e.printStackTrace();
}finally{
try {
ConnectionUtil.closeConnection(connection);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
第四步:配置shiro.ini
[main]
#用户登入路径
authc.loginUrl=/login
#角色验证
roles.unauthorizedUrl=/unauthorized.jsp
#权限验证
perms.unauthorizedUrl=/unauthorized.jsp
myRealm=com.shiro.realm.MyRealm
securityManager.realms=$myRealm
[urls]
#该路径为匿名登入
/login=anon
#身份验证后才能登入
/admin=authc
#该路径验证是否拥有teacher角色
/student=roles[teacher]
#该路径验证该角色是否拥有权限
/teacher=perms["student:delete"]
第五步:loginServlet:和上一章一样