第七章:自定义Realm,从数据库中获取数据进行认证【重点】

工程结构

          

一、建立数据库,数据库名shiro

用户表users、角色表roles、权限表permissions

一个用户有多个角色,一个角色有多种权限

CREATE TABLE `users` (
  `id` int(11) NOT NULL,
  `userName` varchar(20) DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  `roleId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_ID_ROLES_USERS` (`roleId`),
  CONSTRAINT `FK_ID_ROLES_USERS` FOREIGN KEY (`roleId`) REFERENCES `roles` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `roles` (
  `id` int(11) NOT NULL,
  `roleName` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `permissions` (
  `id` int(11) NOT NULL,
  `permissionName` varchar(50) DEFAULT NULL,
  `roleId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_ID_ROLES_PERMISSIONS` (`roleId`),
  CONSTRAINT `FK_ID_ROLES_PERMISSIONS` FOREIGN KEY (`roleId`) REFERENCES `roles` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入测试数据:

    

     

     

二、在pom.xml中添加mysql数据库驱动包

<!-- mysql数据库驱动包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.37</version>
		</dependency>

三、添加IO包

<!-- IO包 -->
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.5</version>
		</dependency>

四、在src/main/resources下创建db.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/shiro?useUnicod=true&characterEncoding=utf-8
userName=root
password=123456

五、创建包com.java1234.common,包下创建连接数据库的工具类DBHelper.java

package com.java1234.common;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

/**
 * 连接数据库
 */
public class DBHelper {
	
	// 驱动参数
	private static Connection conn = null;
	private static PreparedStatement ps = null;
	
	// 连接
	public static Connection getConnection(String driverClassName, 
			String url, String userName, String password) throws Exception {
		try {
			Class.forName(driverClassName);
			conn = DriverManager.getConnection(url, userName, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
	public static PreparedStatement getPreparedStatement(Connection conn, String sql) throws Exception {
		try {
			ps = conn.prepareStatement(sql);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ps;
	}
	
	// 释放资源
	public static void closePreparedStatement(PreparedStatement ps) throws Exception {
		try {
			if (ps != null) {
				ps.close();
				ps = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void closeConnection(Connection conn) throws Exception {
		try {
			if (conn != null) {
				conn.close();
				conn = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void closeResultSet(ResultSet rs) throws Exception {
		try {
			if (rs != null) {
				rs.close();
				rs = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static String getValueByKey(String filename, String key) {
		Properties ps = new Properties();
		InputStream is = null;
		try {
			is = new BufferedInputStream(new FileInputStream(filename));
            ps.load(is);
            String value = ps.getProperty(key);
            return value;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			if (is != null) {
                try {
                    is.close();
                    is = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
		}
	}
}

六、创建测试类,测试数据库是否连接成功

package com.java1234.test;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import com.java1234.common.DBHelper;

public class DbTest {
	public static void main(String[] args) {
		String filename = "src\\main\\resources\\db.properties";
		
		String driverClassName = getValueByKey(filename, "driverClassName");
		String url = getValueByKey(filename, "url");
		String userName = getValueByKey(filename, "userName");
		String password = getValueByKey(filename, "password");
		
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		try {
			conn = DBHelper.getConnection(driverClassName, url, userName, password);
			String sql = "SELECT * FROM users";
			ps = DBHelper.getPreparedStatement(conn, sql);
			rs = ps.executeQuery();
			
			while (rs.next()) {
				Integer db_id = rs.getInt(1);
				String db_userName = rs.getString(2);
				String db_password = rs.getString(3);
				System.out.println(db_id + " | " + db_userName + " | " + db_password);
				System.out.println();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				DBHelper.closeResultSet(rs);
				DBHelper.closePreparedStatement(ps);
				DBHelper.closeConnection(conn);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
		
	}
	public static String getValueByKey(String filename, String key) {
		Properties ps = new Properties();
		InputStream is = null;
		try {
			is = new BufferedInputStream(new FileInputStream(filename));
            ps.load(is);
            String value = ps.getProperty(key);
            return value;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			if (is != null) {
                try {
                    is.close();
                    is = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
		}
	}
}

结果: 数据库连接成功!

1 | java1234 | 123456

2 | jack | 123

3 | marry | 234

4 | json | 345

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

七、创建POJO类和DAO类

Users.java

private Integer id;
	private String userName;
	private String password;
	private Roles role;

Roles.java

private Integer id;
	private String roleName;

Permissions.java

private Integer id;
	private String permissionName;
	private Roles role;

UserDao.java

package com.java1234.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashSet;
import java.util.Set;

import com.java1234.common.DBHelper;
import com.java1234.entities.Users;

public class UserDao {
	
	// 数据库参数
	private static Connection conn = null;
	private static PreparedStatement ps = null;
	private static ResultSet rs = null;
	
	// 连接参数
	private static String filename = null;
	private static String jdbc_driverClassName = null;
	private static String jdbc_url = null;
	private static String jdbc_userName = null;
	private static String jdbc_password = null;
	
	static {
//		filename = "src\\main\\resources\\db.properties";
		filename = "G:\\Test2\\ShiroWeb\\src\\main\\resources\\db.properties";
		jdbc_driverClassName = DBHelper.getValueByKey(filename, "driverClassName");
		jdbc_url = DBHelper.getValueByKey(filename, "url");
		jdbc_userName = DBHelper.getValueByKey(filename, "userName");
		jdbc_password = DBHelper.getValueByKey(filename, "password");
		
		try {
			conn = DBHelper.getConnection(jdbc_driverClassName, jdbc_url, jdbc_userName, jdbc_password);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	/**
	 * 根据用户名获取用户信息
	 * @param userName 用户输入的用户名
	 * @return
	 * @throws Exception
	 */
	public Users getByUserName(String userName) throws Exception {
		Users user = null;
		String sql = "SELECT * FROM users WHERE userName = ? LIMIT 1";
		try {
			ps = DBHelper.getPreparedStatement(conn, sql);
			ps.setString(1, userName);
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				user = new Users();
				user.setId(rs.getInt(1));
				user.setUserName(rs.getString(2));
				user.setPassword(rs.getString(3));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return user;
	}
	
	/**
	 * 根据用户名获取用户的角色
	 * @param userName
	 * @return 角色列表
	 * @throws Exception
	 */
	public Set<String> getRoles(String userName) throws Exception {
		Set<String> roles = new HashSet<String>();
		String sql = "SELECT r.roleName FROM users u LEFT JOIN roles r ON u.roleId = r.id WHERE u.userName = ?";
		try {
			ps = DBHelper.getPreparedStatement(conn, sql);
			ps.setString(1, userName);
			rs = ps.executeQuery();
			while (rs.next()) {
				roles.add(rs.getString("roleName"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return roles;
	}
	
	public Set<String> getPermissions(String userName) throws Exception {
		Set<String> permissions = new HashSet<String>();
		String sql = "SELECT p.permissionName FROM users u LEFT "
				+ "JOIN roles r ON u.roleId = r.id LEFT "
				+ "JOIN permissions p ON r.id = p.roleId WHERE u.userName = ?";
		try {
			ps = DBHelper.getPreparedStatement(conn, sql);
			ps.setString(1, userName);
			rs = ps.executeQuery();
			while (rs.next()) {
				permissions.add(rs.getString("permissionName"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return permissions;
	}
}

八、创建自定义Realm

创建com.java1234.realm.MyRealm.java

package com.java1234.realm;

import java.util.Iterator;
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 com.java1234.dao.UserDao;
import com.java1234.entities.Users;

public class MyRealm extends AuthorizingRealm {

	private UserDao userDao = new UserDao();

	/**
	 * 验证当前登录的用户
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {

		String userName = (String) token.getPrincipal();
		try {
			Users user = userDao.getByUserName(userName); // 根据用户名获取用户
			if (user != null) {
				AuthenticationInfo info = new SimpleAuthenticationInfo(
						user.getUserName(), user.getPassword(), "XXX");
				return info;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}

	/**
	 * 为当前用户授予角色和权限, 在用户成功登录后才会执行这个方法
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {

		/**
		 * 获取用户名,这里的用户名是数据库中的用户名,即从上面的方法doGetAuthenticationInfo()
		 * 中获取的user中的user.getUserName()中获取到的合法的用户名, 通过这个用户名可以获取到用户拥有的角色和权限
		 */
		String userName = (String) principals.getPrimaryPrincipal();
		
		// 绑定用户所拥有的角色和权限
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		try {
			// 根据用户名获取用户角色,并将其绑定到info中
			Set<String> roles = userDao.getRoles(userName);
			Iterator<String> iterator = roles.iterator();
			while (iterator.hasNext()) {
				System.out.println(iterator.next());
			}
			info.setRoles(roles);	
			// 根据用户名获取用户权限,并剑气绑定到info中
			Set<String> permissions = userDao.getPermissions(userName);
			Iterator<String> iterator2 = permissions.iterator();
			while (iterator2.hasNext()) {
				System.out.println(iterator2.next());
			}
			info.setStringPermissions(permissions);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return info;
	}
}

九、将自定义Realm配置到shiro.ini中(包.类的形式)

[main]
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized.jsp  
perms.unauthorizedUrl=/unauthorized.jsp  
myRealm=com.java1234.realm.MyRealm
securityManager.realms=$myRealm
[urls]
/login=anon
/admin?=authc
/student=roles[teacher]
/teacher=perms["user:create"]

十、测试

 (1)用户java123456登录

   

后台打印:

admin
user:*
admin
user:*

 (2) 用户jack登录

    

后台打印:

teacher
student:*
teacher
student:*

 

posted @ 2017-05-07 17:09  半生戎马,共话桑麻、  阅读(154)  评论(0)    收藏  举报
levels of contents