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 ...
随机推荐
- 从CakePHP 1.3升级到2.5
从CakePHP 1.3升级到2.5 摘要:最近把一个CakePHP 1.3的项目升级到了2.x,当然就用最新的版本2.5.3了,结果基本满意.本文记录了升级的过程,包括使用的工具,遇到的问题和相应的 ...
- windows下使用mingw和msys编译GOTOBLAS和OpenBLAS
在windows下利用msys编译openBLAS若遇到错误提示: gcc: CreateProcess : No such file or directory 问题原因参考:http://www.c ...
- NPOI解析Excel
园子的文章: http://www.cnblogs.com/csqb-511612371/category/654604.html 关键就是如何解析Excel表头,特别是合并单元格的..还有对应NPO ...
- C项目实践--学生成绩管理系统
1.功能需求分析 学生成绩管理系统是对学生基本信息及成绩的管理.本程序主要实现了对学生的学号.姓名等基本信息以及各项学科成绩进行增加.删除.修改.查询和保存到磁盘文件等操作.主要功能描述如下: (1) ...
- C++不能在栈上申请动态内存,而只能依靠指针
以下三种情况皆错,都编译不过: int main(int argc, char* argv[]) { int a; int b[a]; } int main(int argc, char* argv[ ...
- CRM 2011 开发中遇到的问题小结
1.将Retrive 方法改成 RetrieveMultiple时 如果指定的ColumnSet 没有指定主键(entiryname+id),要显示增加实体的主键.否则在调用 Retrieve方法时返 ...
- bzoj1835: [ZJOI2010]base 基站选址
新的一年新的开始.结果第一题就用了几乎一周.而且感觉很不好. 先检讨自己.最近写的各种数据结构模板基本没打过出来,各种细节崩盘,这题线段树都居然被lazy标记没清零卡挂. DP还是博大精深,这东西感觉 ...
- UITableview控件简单介绍
注意点:数据源方法只能在控制器里设置 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UITableView ...
- UI:归档、反归档、数据持久化
支持的文件读写类型:字符串.数组.字典.NSdata (可变的.不可变的.共有8个类) 对于数组.字典在写入文件时,其中的元素也必须是以上四种类型之一. 支持的数据类型有限.且简单 写入文件: 字符 ...
- HDU 4891 The Great Pan (题意题+模拟)
题意:给定一个文章,问你有多少种读法,计算方法有两种,如果在$中,如果有多个空格就算n+1,如果是一个就算2的次方,如果在{}中, 那么就是把每个空格数乘起来. 析:直接模拟,每次计算一行,注意上一行 ...