本文介绍shiro通过jdbc连接数据库,连接池采用阿里巴巴的druid的连接池

参考文档:https://www.w3cschool.cn/shiro/xgj31if4.html

     https://www.w3cschool.cn/shiro/h5it1if8.html

pom.xml的配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <artifactId>shiro-example-chapter2</artifactId>
  6. <groupId>com.github.zhangkaitao</groupId>
  7. <version>SNAPSHOT</version>
  8. <modelVersion>4.0.0</modelVersion>
  9.  
  10. <build>
  11. <plugins>
  12. <plugin>
  13. <groupId>org.apache.maven.plugins</groupId>
  14. <artifactId>maven-compiler-plugin</artifactId>
  15. <configuration>
  16. <source>1.7</source>
  17. <target>1.7</target>
  18. </configuration>
  19. </plugin>
  20. </plugins>
  21. </build>
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.slf4j</groupId>
  25. <artifactId>slf4j-api</artifactId>
  26. <version>1.7.16</version>
  27. </dependency>
  28.  
  29. <dependency>
  30. <groupId>log4j</groupId>
  31. <artifactId>log4j</artifactId>
  32. <version>1.2.17</version>
  33. </dependency>
  34.  
  35. <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
  36. <dependency>
  37. <groupId>org.slf4j</groupId>
  38. <artifactId>slf4j-log4j12</artifactId>
  39. <version>1.7.25</version>
  40. <scope>test</scope>
  41. </dependency>
  42.  
  43. <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
  44. <dependency>
  45. <groupId>commons-logging</groupId>
  46. <artifactId>commons-logging</artifactId>
  47. <version>1.1.3</version>
  48. </dependency>
  49.  
  50. <dependency>
  51. <groupId>junit</groupId>
  52. <artifactId>junit</artifactId>
  53. <version>4.9</version>
  54. <scope>test</scope>
  55. </dependency>
  56.  
  57. <dependency>
  58. <groupId>org.apache.shiro</groupId>
  59. <artifactId>shiro-core</artifactId>
  60. <version>1.2.2</version>
  61. </dependency>
  62.  
  63. <dependency>
  64. <groupId>mysql</groupId>
  65. <artifactId>mysql-connector-java</artifactId>
  66. <version>5.1.25</version>
  67. </dependency>
  68. <dependency>
  69. <groupId>com.alibaba</groupId>
  70. <artifactId>druid</artifactId>
  71. <version>1.1.8</version>
  72. </dependency>
  73.  
  74. </dependencies>
  75.  
  76. </project>

shiro.ini 文件的配置

  1. [main]
  2. dataSource=com.alibaba.druid.pool.DruidDataSource
  3. dataSource.driverClassName=com.mysql.jdbc.Driver
  4. dataSource.url=jdbc:mysql://localhost:3306/shiro
  5. dataSource.username=root
  6. dataSource.password=123456
  7. jdbcRealm.dataSource=$dataSource
  8.  
  1. jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
  1. securityManager.realms=$jdbcRealm
  1. jdbcRealm shiro框架已经集成的安全域,安全域的作用是将资源(数据库,缓存,磁盘文件等)中用户身份的集合和需要匹配的集合进行验证,决定登录用户的身份是否能验证成功的功能。如果要自定义安全域,只要继承
  1. AuthorizingRealm 这个接口。实现doGetAuthenticationInfo() 身份验证这个方法即可。
  2.  
  3. 测试类的方法
  1. public class TestJdbcLogin{
    @Test
  2. public void testJDBCRealm() {
  3. //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
  4. Factory<org.apache.shiro.mgt.SecurityManager> factory =
  5. new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
  6.  
  7. //2、得到SecurityManager实例 并绑定给SecurityUtils
  8. org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
  9. SecurityUtils.setSecurityManager(securityManager);
  10.  
  11. //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
  12. Subject subject = SecurityUtils.getSubject();
  13. UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
  14.  
  15. try {
  16. //4、登录,即身份验证
  17. subject.login(token);
  18. } catch (IncorrectCredentialsException e) {
  19. //5、身份验证失败
  20. e.printStackTrace();
  21. System.out.println("密码错误");
  22. }catch (DisabledAccountException e){
  23. System.out.println("禁用的账户");
  24. }
  25.  
  26. Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
  27.  
  28. //6、退出
  29. subject.logout();
  30. }
    }

JdbcRealm 类

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5.  
  6. package org.apache.shiro.realm.jdbc;
  7.  
  8. import java.sql.Connection;
  9. import java.sql.PreparedStatement;
  10. import java.sql.ResultSet;
  11. import java.sql.SQLException;
  12. import java.util.Collection;
  13. import java.util.Iterator;
  14. import java.util.LinkedHashSet;
  15. import java.util.Set;
  16. import javax.sql.DataSource;
  17. import org.apache.shiro.authc.AccountException;
  18. import org.apache.shiro.authc.AuthenticationException;
  19. import org.apache.shiro.authc.AuthenticationInfo;
  20. import org.apache.shiro.authc.AuthenticationToken;
  21. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  22. import org.apache.shiro.authc.UnknownAccountException;
  23. import org.apache.shiro.authc.UsernamePasswordToken;
  24. import org.apache.shiro.authz.AuthorizationException;
  25. import org.apache.shiro.authz.AuthorizationInfo;
  26. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  27. import org.apache.shiro.config.ConfigurationException;
  28. import org.apache.shiro.realm.AuthorizingRealm;
  29. import org.apache.shiro.subject.PrincipalCollection;
  30. import org.apache.shiro.util.JdbcUtils;
  31. import org.apache.shiro.util.ByteSource.Util;
  32. import org.slf4j.Logger;
  33. import org.slf4j.LoggerFactory;
  34.  
  35. public class JdbcRealm extends AuthorizingRealm {
  36. protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
  37. protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";
  38. protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
  39. protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";
  40. private static final Logger log = LoggerFactory.getLogger(JdbcRealm.class);
  41. protected DataSource dataSource;
  42. protected String authenticationQuery = "select password from users where username = ?";
  43. protected String userRolesQuery = "select role_name from user_roles where username = ?";
  44. protected String permissionsQuery = "select permission from roles_permissions where role_name = ?";
  45. protected boolean permissionsLookupEnabled = false;
  46. protected JdbcRealm.SaltStyle saltStyle;
  47.  
  48. public JdbcRealm() {
  49. this.saltStyle = JdbcRealm.SaltStyle.NO_SALT;
  50. }
  51.  
  52. public void setDataSource(DataSource dataSource) {
  53. this.dataSource = dataSource;
  54. }
  55.  
  56. public void setAuthenticationQuery(String authenticationQuery) {
  57. this.authenticationQuery = authenticationQuery;
  58. }
  59.  
  60. public void setUserRolesQuery(String userRolesQuery) {
  61. this.userRolesQuery = userRolesQuery;
  62. }
  63.  
  64. public void setPermissionsQuery(String permissionsQuery) {
  65. this.permissionsQuery = permissionsQuery;
  66. }
  67.  
  68. public void setPermissionsLookupEnabled(boolean permissionsLookupEnabled) {
  69. this.permissionsLookupEnabled = permissionsLookupEnabled;
  70. }
  71.  
  72. public void setSaltStyle(JdbcRealm.SaltStyle saltStyle) {
  73. this.saltStyle = saltStyle;
  74. if (saltStyle == JdbcRealm.SaltStyle.COLUMN && this.authenticationQuery.equals("select password from users where username = ?")) {
  75. this.authenticationQuery = "select password, password_salt from users where username = ?";
  76. }
  77.  
  78. }
  79.  
  80. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  81. UsernamePasswordToken upToken = (UsernamePasswordToken)token;
  82. String username = upToken.getUsername();
  83. if (username == null) {
  84. throw new AccountException("Null usernames are not allowed by this realm.");
  85. } else {
  86. Connection conn = null;
  87. SimpleAuthenticationInfo info = null;
  88.  
  89. try {
  90. String salt;
  91. try {
  92. conn = this.dataSource.getConnection();
  93. String password = null;
  94. salt = null;
  95. switch(this.saltStyle) {
  96. case NO_SALT:
  97. password = this.getPasswordForUser(conn, username)[0];
  98. break;
  99. case CRYPT:
  100. throw new ConfigurationException("Not implemented yet");
  101. case COLUMN:
  102. String[] queryResults = this.getPasswordForUser(conn, username);
  103. password = queryResults[0];
  104. salt = queryResults[1];
  105. break;
  106. case EXTERNAL:
  107. password = this.getPasswordForUser(conn, username)[0];
  108. salt = this.getSaltForUser(username);
  109. }
  110.  
  111. if (password == null) {
  112. throw new UnknownAccountException("No account found for user [" + username + "]");
  113. }
  114.  
  115. info = new SimpleAuthenticationInfo(username, password.toCharArray(), this.getName());
  116. if (salt != null) {
  117. info.setCredentialsSalt(Util.bytes(salt));
  118. }
  119. } catch (SQLException var12) {
  120. salt = "There was a SQL error while authenticating user [" + username + "]";
  121. if (log.isErrorEnabled()) {
  122. log.error(salt, var12);
  123. }
  124.  
  125. throw new AuthenticationException(salt, var12);
  126. }
  127. } finally {
  128. JdbcUtils.closeConnection(conn);
  129. }
  130.  
  131. return info;
  132. }
  133. }
  134.  
  135. private String[] getPasswordForUser(Connection conn, String username) throws SQLException {
  136. boolean returningSeparatedSalt = false;
  137. String[] result;
  138. switch(this.saltStyle) {
  139. case NO_SALT:
  140. case CRYPT:
  141. case EXTERNAL:
  142. result = new String[1];
  143. break;
  144. case COLUMN:
  145. default:
  146. result = new String[2];
  147. returningSeparatedSalt = true;
  148. }
  149.  
  150. PreparedStatement ps = null;
  151. ResultSet rs = null;
  152.  
  153. try {
  154. ps = conn.prepareStatement(this.authenticationQuery);
  155. ps.setString(1, username);
  156. rs = ps.executeQuery();
  157.  
  158. for(boolean foundResult = false; rs.next(); foundResult = true) {
  159. if (foundResult) {
  160. throw new AuthenticationException("More than one user row found for user [" + username + "]. Usernames must be unique.");
  161. }
  162.  
  163. result[0] = rs.getString(1);
  164. if (returningSeparatedSalt) {
  165. result[1] = rs.getString(2);
  166. }
  167. }
  168. } finally {
  169. JdbcUtils.closeResultSet(rs);
  170. JdbcUtils.closeStatement(ps);
  171. }
  172.  
  173. return result;
  174. }
  175.  
  176. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  177. if (principals == null) {
  178. throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
  179. } else {
  180. String username = (String)this.getAvailablePrincipal(principals);
  181. Connection conn = null;
  182. Set<String> roleNames = null;
  183. Set permissions = null;
  184.  
  185. try {
  186. conn = this.dataSource.getConnection();
  187. roleNames = this.getRoleNamesForUser(conn, username);
  188. if (this.permissionsLookupEnabled) {
  189. permissions = this.getPermissions(conn, username, roleNames);
  190. }
  191. } catch (SQLException var11) {
  192. String message = "There was a SQL error while authorizing user [" + username + "]";
  193. if (log.isErrorEnabled()) {
  194. log.error(message, var11);
  195. }
  196.  
  197. throw new AuthorizationException(message, var11);
  198. } finally {
  199. JdbcUtils.closeConnection(conn);
  200. }
  201.  
  202. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
  203. info.setStringPermissions(permissions);
  204. return info;
  205. }
  206. }
  207.  
  208. protected Set<String> getRoleNamesForUser(Connection conn, String username) throws SQLException {
  209. PreparedStatement ps = null;
  210. ResultSet rs = null;
  211. LinkedHashSet roleNames = new LinkedHashSet();
  212.  
  213. try {
  214. ps = conn.prepareStatement(this.userRolesQuery);
  215. ps.setString(1, username);
  216. rs = ps.executeQuery();
  217.  
  218. while(rs.next()) {
  219. String roleName = rs.getString(1);
  220. if (roleName != null) {
  221. roleNames.add(roleName);
  222. } else if (log.isWarnEnabled()) {
  223. log.warn("Null role name found while retrieving role names for user [" + username + "]");
  224. }
  225. }
  226. } finally {
  227. JdbcUtils.closeResultSet(rs);
  228. JdbcUtils.closeStatement(ps);
  229. }
  230.  
  231. return roleNames;
  232. }
  233.  
  234. protected Set<String> getPermissions(Connection conn, String username, Collection<String> roleNames) throws SQLException {
  235. PreparedStatement ps = null;
  236. LinkedHashSet permissions = new LinkedHashSet();
  237.  
  238. try {
  239. ps = conn.prepareStatement(this.permissionsQuery);
  240. Iterator i$ = roleNames.iterator();
  241.  
  242. while(i$.hasNext()) {
  243. String roleName = (String)i$.next();
  244. ps.setString(1, roleName);
  245. ResultSet rs = null;
  246.  
  247. try {
  248. rs = ps.executeQuery();
  249.  
  250. while(rs.next()) {
  251. String permissionString = rs.getString(1);
  252. permissions.add(permissionString);
  253. }
  254. } finally {
  255. JdbcUtils.closeResultSet(rs);
  256. }
  257. }
  258. } finally {
  259. JdbcUtils.closeStatement(ps);
  260. }
  261.  
  262. return permissions;
  263. }
  264.  
  265. protected String getSaltForUser(String username) {
  266. return username;
  267. }
  268.  
  269. public static enum SaltStyle {
  270. NO_SALT,
  271. CRYPT,
  272. COLUMN,
  273. EXTERNAL;
  274.  
  275. private SaltStyle() {
  276. }
  277. }
  278. }

标红的查询语句正是shiro框架已经集成的查询语句,所以建表的时候要根据相应的表名建表

另外可以参考这篇文章:http://blog.51cto.com/luchunli/1828080

  1.  

shiro 通过jdbc连接数据库的更多相关文章

  1. JDBC连接数据库

    JDBC连接数据库 1.加载JDBC驱动程序. Class.forName("com.mysql.jdbc.Driver"); 建立连接,. Connection conn = D ...

  2. java开发中JDBC连接数据库代码和步骤

    JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.l ...

  3. java开发JDBC连接数据库详解

    JDBC连接数据库 好文一定要让大家看见 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机) ...

  4. 【转】Java开发中JDBC连接数据库代码和步骤总结

    (转自:http://www.cnblogs.com/hongten/archive/2011/03/29/1998311.html) JDBC连接数据库 创建一个以JDBC连接数据库的程序,包含7个 ...

  5. 使用配置文件来配置JDBC连接数据库

    1.管理数据库连接的Class 代码如下: package jdbcTest;import java.sql.Connection;import java.sql.DriverManager;impo ...

  6. Java中JDBC连接数据库代码和步骤详解总结

    JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤:         1.加载JDBC驱动程序:         在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Jav ...

  7. 完整java开发中JDBC连接数据库代码和步骤

    JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.l ...

  8. JDBC连接数据库(PreparedStatement)

    PreparedStatement是在数据库端防止SQL注入漏洞的SQL方法这里演示了一些基本使用方法同样使用Oracle数据库,之前已经手动建立了一张t_account表数据库代码参见上一篇< ...

  9. JDBC连接数据库演示

    今天重新学习了JDBC连接数据库,使用的数据库是Oracle,在运行前已经手动建立了一张t_user表,建表信息如下: create table t_user( card_id ) primary k ...

随机推荐

  1. IO流(SequenceInputStream序列流--文件拆分与合并)

    一.文件拆分 1.将一个文件按照规定的大小进行分割成多个文件并将被分割详细信息保存至配置信息中 Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载,属性列表 ...

  2. OpenGL中视点模型坐标的理解

    个人的理解: gluLookAt中的eye.center和up的坐标原点是ModelView中的坐标原点,右手坐标系,Z轴正向指向显示器外侧 glOrtho中的near和far参数距离相对eye而言, ...

  3. make eval builtin function

    1 eval的返回值是空字符串,因此它可以用于Makefile的任何位置而不引起错误 2 eval函数的作用效果 生成Makefile的动态部分,即eval用于增加Makefile的构成部分. 也就是 ...

  4. Java 解析excel2003和2007区别和兼容性问题(POI操作)

    最近在使用POI对excel操作中发现一些问题,2003和2007的区别还是蛮大的: 2007相关的包: poi-3.9.jar poi-examples-3.8.jar poi-excelant-3 ...

  5. publish and submit

    http://blog.csdn.net/w_jewelry/article/details/8123639 1.Gerrit里点击“publish and submit”提示如下:Your chan ...

  6. 闲得蛋疼,JavaScript版本BadApple

    参考Vim版本的BadApple改写而成.由于加载数据比较大,可能网速不给力的童鞋效果不太好,多刷新几次就好了,^_^.运行环境:支持HTML5 Canvas的浏览器.​1. 代码:$(functio ...

  7. codeforces 686D D. Kay and Snowflake(dfs)

    题目链接: D. Kay and Snowflake time limit per test 3 seconds memory limit per test 256 megabytes input s ...

  8. GC回收算法--当女友跟你提分手!

    Java语言引入了垃圾回收机制,让C++语言中令人头疼的内存管理问题迎刃而解,使得我们Java狗每天开开心心地创建对象而不用管对象死活,这些都是Java的垃圾回收机制带来的好处.但是Java的垃圾回收 ...

  9. CF 949 D Curfew —— 二分答案

    题目:http://codeforces.com/contest/949/problem/D 先二分一个答案,让两边都至少满足这个答案: 由于越靠中间的房间越容易满足(被检查的时间靠后),所以策略就是 ...

  10. bzoj4326

    二分+树剖+差分 之前的做法naive,莫名其妙的wa,明明uoj95分 看到最小最大上二分,树上路径问题直接剖,然后问题就转化成了一个判定问题,每次二分出最长路径长度,问能不能达到.那么我们就把所有 ...