shiro入门实战笔记(10)--自定义Realm

[本系列文章是博主的学习笔记,而非经典教程,特此说明]

首先,我们先来回顾下面这张图:


接着,我们在来回顾一下Realm的概念:Realm可以有1个或多个,可以认为是安全实体数据源,即用于获取安全实体的;可以是JDBC 实现,也可以是LDAP 实现,或者内存实现等等;由用户提供;注意:Shiro不知道你的用户/权限存储在哪及以何种格式存储;所以我们一般在应用中都需要实现自己的Realm;这个概念通俗的将,就是我们对于权限配置的保存方式是那一种形式。在我们前面的一系列举例中都是使用shiro.ini配置文件的方式。本文我们来介绍使用数据库的方式来存储用户,角色,权限等信息。好了,现在我们回顾了这些基本概念之后,开始我们的正文部分吧。

准备工作:

a.操作系统:win7 x64

b.开发工具:myeclipse 2014,jdk1.7,maven3.3.3,mysql5.0,jsp基础

-----------------------------------------------------------------------------------------------------------------------------------------------------

正文开始:

一.创建数据库,表及配置信息

1.创建数据库,博主这里使用图形化的mysql管理工具创建名称为shiro的数据库,读者可以按照自己的实际情况选择。

2.创建角色表,我们将角色表命名为t_role,表格数据是将shiro.ini中的[roles]部分转换而来,具体内容如下图所示

CREATE TABLE `t_role` (
  `Id` int(11) NOT NULL auto_increment,
  `roleName` varchar(255) default NULL,
  PRIMARY KEY  (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

3.创建用户表,我们将用户表命名为t_user,表格数据是将shiro.ini中的[user]部分转换而来,具体内容如下图所示:

CREATE TABLE `t_user` (
  `Id` int(11) NOT NULL auto_increment,
  `userName` varchar(255) default NULL,
  `password` varchar(255) 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 DEFAULT CHARSET=utf8


4.创建权限表,我们将权限表命名为t_permission,表格数据是讲shiro.ini中的[roles]部分转换而来,具体内容如下图所示:

CREATE TABLE `t_permission` (
  `Id` int(11) NOT NULL auto_increment,
  `permissionName` varchar(255) 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 DEFAULT CHARSET=utf8



5.注意,上面的3张表之间是存在主外键关系的,具体内容如下图:

t_permission表中的roldId与t_role表中的Id建立主外键关系。

t_user表中的roleId与t_role表中的Id建立主外键关系。


二.创建我们本文示例工程shiro07

1.创建工程我们可以直接将shiro05工程复制过来,然后修改为shiro07工程目录,具体内容如下图所示:


2.修改pom文件,具体内容如下:

<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/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.java.shiro</groupId>
	<artifactId>shiro06</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>shiro05 Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>1.2.4</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.13</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.22</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>shiro05</finalName>
	</build>
</project>
写入上面的依赖,保存,maven会帮助我们自动的下载相关的包。下载号之后,我们在工程的maven dependencies下就可以看到如下内容,如果有遗漏,请读者认真检查。



3.创建DbUtil.java文件,具体内容如下:

package com.java.util;

import java.sql.Connection;
import java.sql.DriverManager;

/**
 * 数据库工具类
 */
public class DbUtil {

	/**
	 * 获取数据库连接
	 * @return
	 * @throws Exception
	 */
	public Connection getCon() throws Exception{
		Class.forName("com.mysql.jdbc.Driver");
		Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/shiro", "root", "1234");
		return con;
	}
	
	/**
	 * 关闭数据库连接
	 * @param con
	 * @throws Exception
	 */
	public void closeCon(Connection con)throws Exception{
		if(con!=null){
			con.close();
		}
	}
	
	public static void main(String[] args) {
		DbUtil dbUtil=new DbUtil();
		try {
			dbUtil.getCon();
			System.out.println("数据库连接成功");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("数据库连接失败");
		}
	}
}
为方便介绍后面的内容,这里请大家先进行单元测试,如果有问题,请先按照错误提示进行解决。

4.创建com.java.realm包,创建MyRealm.java文件,具体内容如下:

package com.java.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.java.dao.UserDao;
import com.java.entity.User;
import com.java.util.DbUtil;

/**
 *@author 作者 E-mail:
 *@version 创建时间:2016年2月15日下午6:59:38
 *类说明
 */
public class MyRealm extends AuthorizingRealm{
	private UserDao userDao = new UserDao();
	private DbUtil dbUtil = new DbUtil();
	/* (non-Javadoc)
	 * @see 为当前用户授予角色与权限
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) {
		String userName = (String) principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		Connection con = null;
		try{
			con=dbUtil.getCon();
			authorizationInfo.setRoles(userDao.getRoles(con,userName));
			authorizationInfo.setStringPermissions(userDao.getPermission(con,userName));
		}catch(Exception e){
			//自行处理
		}
		return authorizationInfo;
	}

	/* (non-Javadoc)
	 * @see 获取认证信息,验证当前登陆的用户
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		String userName = (String) token.getPrincipal();
		Connection con = null;
		try{
			con = dbUtil.getCon();
			User user = userDao.getByUserName(con, userName);
			if(user!=null){
				AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xx");
				return authcInfo;
			}else{
				return null;
			}
		}catch(Exception e){
			//自行处理
		}finally{
			try {
				dbUtil.closeCon(con);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}

}
5.创建com.java.dao包,创建UserDao.java文件,具体内容如下:

package com.java.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashSet;
import java.util.Set;

import javax.swing.text.html.HTMLDocument.HTMLReader.ParagraphAction;

import com.java.entity.User;

/**
 *@author 作者 E-mail:
 *@version 创建时间:2016年2月15日下午8:20:
 *类说明
 */
public class UserDao {
	public User getByUserName(Connection con,String userName)throws Exception{
		User resultUser = null;
		String sql = "select * from t_user where  userName=?";
		PreparedStatement pstment = con.prepareStatement(sql);
		pstment.setString(1,userName);
		ResultSet rs = pstment.executeQuery();
		if(rs.next()){
			resultUser = new User();
			resultUser.setId(rs.getInt("id"));
			resultUser.setUserName(rs.getString("userName"));
			resultUser.setPassword(rs.getString("password"));
		}
		return resultUser;
	}

	public Set<String> getRoles(Connection con, String userName)throws Exception {
		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 pstment = con.prepareStatement(sql);
		pstment.setString(1,userName);
		ResultSet rs = pstment.executeQuery();
		while(rs.next()){
			roles.add(rs.getString("roleName"));
		}
		return roles;
	}

	public Set<String> getPermission(Connection con, String userName) throws Exception {
		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 pstment = con.prepareStatement(sql);
		pstment.setString(1,userName);
		ResultSet rs = pstment.executeQuery();
		while(rs.next()){
			permissions.add(rs.getString("permissionName"));
		}
		return null;
	}
}

6.创建com.java.entity包,创建User.java文件,具体内容如下:

package com.java.entity;
/**
 *@author 作者 E-mail:
 *@version 创建时间:2016年2月15日下午8:21:45
 *类说明
 */
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;
	}
	
}

7.最后我们来创建新的shiro.ini配置文件,具体内容如下:

[main]
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=/unauthorized.jsp
myRealm=com.java.realm.MyRealm
securityManager.realms=$myRealm
[urls]
/login=anon
/admin*/**=authc
/student=roles[teacher]
/teacher=perms["user:create"]
8.最后,我们部署,启动tomcat,在浏览器中观察在输入正确的用户名密码,错误的用户名密码。控制台如何输出,以及请读者在debug模式下观察程序执行流程。

--------------------------------------------------------------------------------------------------------------------------------------------------

至此,shiro入门实战笔记(10)--自定义Realm结束

备注:

本节所示的内容非常非常非常重要,请各位看官一定亲自动手实践一次,并且在debug模式下跟踪程序执行流程。

参考资料:

官方文档:http://shiro.apache.org/documentation.html

其他博文:http://jinnianshilongnian.iteye.com/blog/2018936










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值