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 = ?";