shiro 通过jdbc连接数据库
本文介绍shiro通过jdbc连接数据库,连接池采用阿里巴巴的druid的连接池
参考文档:https://www.w3cschool.cn/shiro/xgj31if4.html
https://www.w3cschool.cn/shiro/h5it1if8.html
pom.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<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">
<artifactId>shiro-example-chapter2</artifactId>
<groupId>com.github.zhangkaitao</groupId>
<version>SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.16</version>
</dependency> <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency> <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency> </dependencies> </project>
shiro.ini 文件的配置
[main]
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
dataSource.password=123456
jdbcRealm.dataSource=$dataSource
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
securityManager.realms=$jdbcRealm
jdbcRealm shiro框架已经集成的安全域,安全域的作用是将资源(数据库,缓存,磁盘文件等)中用户身份的集合和需要匹配的集合进行验证,决定登录用户的身份是否能验证成功的功能。如果要自定义安全域,只要继承
AuthorizingRealm 这个接口。实现doGetAuthenticationInfo() 身份验证这个方法即可。 测试类的方法
public class TestJdbcLogin{
@Test
public void testJDBCRealm() {
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
try {
//4、登录,即身份验证
subject.login(token);
} catch (IncorrectCredentialsException e) {
//5、身份验证失败
e.printStackTrace();
System.out.println("密码错误");
}catch (DisabledAccountException e){
System.out.println("禁用的账户");
}
Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
//6、退出
subject.logout();
}
}
JdbcRealm 类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package org.apache.shiro.realm.jdbc; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.sql.DataSource;
import org.apache.shiro.authc.AccountException;
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.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.config.ConfigurationException;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.JdbcUtils;
import org.apache.shiro.util.ByteSource.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; public class JdbcRealm extends AuthorizingRealm {
protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";
private static final Logger log = LoggerFactory.getLogger(JdbcRealm.class);
protected DataSource dataSource;
protected String authenticationQuery = "select password from users where username = ?";
protected String userRolesQuery = "select role_name from user_roles where username = ?";
protected String permissionsQuery = "select permission from roles_permissions where role_name = ?";
protected boolean permissionsLookupEnabled = false;
protected JdbcRealm.SaltStyle saltStyle; public JdbcRealm() {
this.saltStyle = JdbcRealm.SaltStyle.NO_SALT;
} public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
} public void setAuthenticationQuery(String authenticationQuery) {
this.authenticationQuery = authenticationQuery;
} public void setUserRolesQuery(String userRolesQuery) {
this.userRolesQuery = userRolesQuery;
} public void setPermissionsQuery(String permissionsQuery) {
this.permissionsQuery = permissionsQuery;
} public void setPermissionsLookupEnabled(boolean permissionsLookupEnabled) {
this.permissionsLookupEnabled = permissionsLookupEnabled;
} public void setSaltStyle(JdbcRealm.SaltStyle saltStyle) {
this.saltStyle = saltStyle;
if (saltStyle == JdbcRealm.SaltStyle.COLUMN && this.authenticationQuery.equals("select password from users where username = ?")) {
this.authenticationQuery = "select password, password_salt from users where username = ?";
} } protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken)token;
String username = upToken.getUsername();
if (username == null) {
throw new AccountException("Null usernames are not allowed by this realm.");
} else {
Connection conn = null;
SimpleAuthenticationInfo info = null; try {
String salt;
try {
conn = this.dataSource.getConnection();
String password = null;
salt = null;
switch(this.saltStyle) {
case NO_SALT:
password = this.getPasswordForUser(conn, username)[0];
break;
case CRYPT:
throw new ConfigurationException("Not implemented yet");
case COLUMN:
String[] queryResults = this.getPasswordForUser(conn, username);
password = queryResults[0];
salt = queryResults[1];
break;
case EXTERNAL:
password = this.getPasswordForUser(conn, username)[0];
salt = this.getSaltForUser(username);
} if (password == null) {
throw new UnknownAccountException("No account found for user [" + username + "]");
} info = new SimpleAuthenticationInfo(username, password.toCharArray(), this.getName());
if (salt != null) {
info.setCredentialsSalt(Util.bytes(salt));
}
} catch (SQLException var12) {
salt = "There was a SQL error while authenticating user [" + username + "]";
if (log.isErrorEnabled()) {
log.error(salt, var12);
} throw new AuthenticationException(salt, var12);
}
} finally {
JdbcUtils.closeConnection(conn);
} return info;
}
} private String[] getPasswordForUser(Connection conn, String username) throws SQLException {
boolean returningSeparatedSalt = false;
String[] result;
switch(this.saltStyle) {
case NO_SALT:
case CRYPT:
case EXTERNAL:
result = new String[1];
break;
case COLUMN:
default:
result = new String[2];
returningSeparatedSalt = true;
} PreparedStatement ps = null;
ResultSet rs = null; try {
ps = conn.prepareStatement(this.authenticationQuery);
ps.setString(1, username);
rs = ps.executeQuery(); for(boolean foundResult = false; rs.next(); foundResult = true) {
if (foundResult) {
throw new AuthenticationException("More than one user row found for user [" + username + "]. Usernames must be unique.");
} result[0] = rs.getString(1);
if (returningSeparatedSalt) {
result[1] = rs.getString(2);
}
}
} finally {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(ps);
} return result;
} protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
if (principals == null) {
throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
} else {
String username = (String)this.getAvailablePrincipal(principals);
Connection conn = null;
Set<String> roleNames = null;
Set permissions = null; try {
conn = this.dataSource.getConnection();
roleNames = this.getRoleNamesForUser(conn, username);
if (this.permissionsLookupEnabled) {
permissions = this.getPermissions(conn, username, roleNames);
}
} catch (SQLException var11) {
String message = "There was a SQL error while authorizing user [" + username + "]";
if (log.isErrorEnabled()) {
log.error(message, var11);
} throw new AuthorizationException(message, var11);
} finally {
JdbcUtils.closeConnection(conn);
} SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
info.setStringPermissions(permissions);
return info;
}
} protected Set<String> getRoleNamesForUser(Connection conn, String username) throws SQLException {
PreparedStatement ps = null;
ResultSet rs = null;
LinkedHashSet roleNames = new LinkedHashSet(); try {
ps = conn.prepareStatement(this.userRolesQuery);
ps.setString(1, username);
rs = ps.executeQuery(); while(rs.next()) {
String roleName = rs.getString(1);
if (roleName != null) {
roleNames.add(roleName);
} else if (log.isWarnEnabled()) {
log.warn("Null role name found while retrieving role names for user [" + username + "]");
}
}
} finally {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(ps);
} return roleNames;
} protected Set<String> getPermissions(Connection conn, String username, Collection<String> roleNames) throws SQLException {
PreparedStatement ps = null;
LinkedHashSet permissions = new LinkedHashSet(); try {
ps = conn.prepareStatement(this.permissionsQuery);
Iterator i$ = roleNames.iterator(); while(i$.hasNext()) {
String roleName = (String)i$.next();
ps.setString(1, roleName);
ResultSet rs = null; try {
rs = ps.executeQuery(); while(rs.next()) {
String permissionString = rs.getString(1);
permissions.add(permissionString);
}
} finally {
JdbcUtils.closeResultSet(rs);
}
}
} finally {
JdbcUtils.closeStatement(ps);
} return permissions;
} protected String getSaltForUser(String username) {
return username;
} public static enum SaltStyle {
NO_SALT,
CRYPT,
COLUMN,
EXTERNAL; private SaltStyle() {
}
}
}
标红的查询语句正是shiro框架已经集成的查询语句,所以建表的时候要根据相应的表名建表
另外可以参考这篇文章:http://blog.51cto.com/luchunli/1828080
shiro 通过jdbc连接数据库的更多相关文章
- JDBC连接数据库
JDBC连接数据库 1.加载JDBC驱动程序. Class.forName("com.mysql.jdbc.Driver"); 建立连接,. Connection conn = D ...
- java开发中JDBC连接数据库代码和步骤
JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.l ...
- java开发JDBC连接数据库详解
JDBC连接数据库 好文一定要让大家看见 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机) ...
- 【转】Java开发中JDBC连接数据库代码和步骤总结
(转自:http://www.cnblogs.com/hongten/archive/2011/03/29/1998311.html) JDBC连接数据库 创建一个以JDBC连接数据库的程序,包含7个 ...
- 使用配置文件来配置JDBC连接数据库
1.管理数据库连接的Class 代码如下: package jdbcTest;import java.sql.Connection;import java.sql.DriverManager;impo ...
- Java中JDBC连接数据库代码和步骤详解总结
JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Jav ...
- 完整java开发中JDBC连接数据库代码和步骤
JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.l ...
- JDBC连接数据库(PreparedStatement)
PreparedStatement是在数据库端防止SQL注入漏洞的SQL方法这里演示了一些基本使用方法同样使用Oracle数据库,之前已经手动建立了一张t_account表数据库代码参见上一篇< ...
- JDBC连接数据库演示
今天重新学习了JDBC连接数据库,使用的数据库是Oracle,在运行前已经手动建立了一张t_user表,建表信息如下: create table t_user( card_id ) primary k ...
随机推荐
- Axure使用笔记
软件设置类 两个矩形的双边框,边框重合: 项目---项目设置---边界对齐---内边界对齐. 自动备份时间设置 文件-自动备份设置-默认15分钟,根据电脑硬件可以调整. Axure 8 可以不用安装 ...
- EF Code-First 学习之旅 数据库初始化 (二)
Context类的基类构造函数有如下的参数 1.无参数 如果没有给基类构造函数添加参数,它会在local SQLEXPRESS server创建数据库,名为{Namespace}.{Context c ...
- redis与spring整合·
单机版: 配置spring配置文件applicationContext.xml <?xml version="1.0" encoding="UTF-8"? ...
- Lightoj 1005 Rooks(DP)
A rook is a piece used in the game of chess which is played on a board of square grids. A rook can o ...
- HDU3974 Assign the task —— dfs时间戳 + 线段树
题目链接:https://vjudge.net/problem/HDU-3974 There is a company that has N employees(numbered from 1 to ...
- C语言算法
选择排序法:用第一个数分别和后面的数比较 冒泡排序法:相邻的两个数比较 01.单词首字母大写&统计单词个数 02: 编写一个函数int pieAdd(int n),计算1!+2!+3!+……+ ...
- 【基于libRTMP的流媒体直播之 AAC、H264 推送】
这段时间在捣腾基于 RTMP 协议的流媒体直播框架,其间参考了众多博主的文章,剩下一些细节问题自行琢磨也算摸索出个门道,现将自己认为比较恼人的 AAC 音频帧的推送和解析.H264 码流的推送和解析以 ...
- hdu4507(数位DP)
题目意思: 给定一个区间,求这段区间中,不含7,对7取余为0,各个位数相加之和对7取余为0的数的平方和. 设d[i][j][k][m]代表长度为i的,对7取余为j的,各个位数相加之和对7取余为k的数的 ...
- 数组方法 Array.prototype
Object.prototype 数组的值是有序的集合,每一个值叫做元素,每一个元素在数组中都有数字位置编号,也就是索引,js中数组是弱类型的,数组中可以含有不同类型的元素.数组元素甚至可以是对象或者 ...
- java笔记之IO3读操作
* 字节输入流操作步骤: * A:创建字节输入流对象 * B:调用read()方法读取数据,并把数据显示在控制台 * C:释放资源 * * 读取数据的方式: * A:int read():一次读取一 ...