maven环境:采用mysql数据库和c3p0连接池。
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>shiroTest</groupId>
<artifactId>shiroTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>
</dependencies>
</project>
数据库:注意表名和列名保持一致。
采用ini配置shiro
[main]
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/test
dataSource.user=root
dataSource.password=root
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm
使用什么数据源对应的属性名保持一致,druid与c3p0属性名不同,最后将jdbcRealm放入securityManager。
java代码:
@Test
public void testHelloworld() {
//1.通过 new IniSecurityManagerFactory 并指定一个 ini 配置文件来创建一个 SecurityManager 工厂;
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro2.ini");
//2.通过工厂得到一个SecurityManager对象实例
SecurityManager securityManager = factory.getInstance();
//3.将SecurityManager绑定到 SecurityUtils,这是一个全局设置,设置一次即可
SecurityUtils.setSecurityManager(securityManager);
//4.通过 SecurityUtils 得到 Subject,其会自动绑定到当前线程;如果在 web 环境在请求结束时需要解除绑定;
Subject subject = SecurityUtils.getSubject();
//5.获取身份验证的 Token,如用户名 / 密码
UsernamePasswordToken token = new UsernamePasswordToken("123", "123");
try {
//6调用 subject.login 方法进行登录,其会自动委托给 SecurityManager.login 方法进行登录
subject.login(token);
System.out.println("成功!");
} catch (AuthenticationException e) {
//7如果身份验证失败请捕获 AuthenticationException 或其子类,
System.out.println("失败!");
}
//8调用subject.isAuthenticated()判断是否登录进来了
System.out.println("是否登录:"+ subject.isAuthenticated());
//9最后可以调用 subject.logout 退出,其会自动委托给 SecurityManager.logout 方法退出。
subject.logout();
}
输出结果:
成功!
是否登录:true
将密码改为1234,再运行结果为:
失败!
是否登录:false
运行时数据源日志Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null,
发现时以为是连接错误,后来发现不影响运行,数据仍然可以得到。
解释一下为什么数据库必须保持列名表名一致:我们使用了这个类org.apache.shiro.realm.jdbc.JdbcRealm,查看源码得:有几句默认的SQL语句。
/**
* The default query used to retrieve account data for the user.
*/
protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
/**
* The default query used to retrieve account data for the user when {@link #saltStyle} is COLUMN.
*/
protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
/**
* The default query used to retrieve the roles that apply to a user.
*/
protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
/**
* The default query used to retrieve permissions that apply to a particular role.
*/
protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";