(十)shiro之自定义Realm以及自定义Realm在web的应用demo
- 数据库设计
- pom.xml
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.shyroke</groupId> <artifactId>shiro_web</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>shiro_web Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>servlet-api</artifactId> <version>6.0.53</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> </dependencies> <build> <finalName>shiro_web</finalName> <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.26</version> <configuration> <!-- 每2秒的间隔扫描一次,实现热部署 --> <scanIntervalSeconds>2</scanIntervalSeconds>
<!-- 设置为手动部署,即在Console中回车即部署 --> <reload>manual</reload> <contextPath>/</contextPath> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>3033</port> </connector> </connectors> </configuration> </plugin> </plugins> </build> </project>
- shiro.ini
[main]
authc.loginUrl= /login
roles.unauthorizedUrl= /unauthorized.jsp
perms.unauthorizedUrl= /unauthorized.jsp
myRealm=com.shyroke.realms.MyRealm
securityManager.realms=$myRealm
[urls]
/index.jsp = authc
/ = authc
/admin.jsp = authc,perms[admin:query]
/jsp/user.jsp = authc,perms[user:*]
/jsp/user_add.jsp = authc,perms[user:add]
/login = anon
/logout = logout
-
myRealm=com.shyroke.realms.MyRealm 表示创建com.shyroke.realms.MyRealm对象,对象名为myRealm。
- login.jsp
<body> <form action="<%=path%>/login" method="post"> userName:<input type="text" name="username" /><br /> passWord:<input type="password" name="password" /><br /> <input type="submit" value="登录"> ${requestScope.emsg} </form> </body>
- LoginServlet.java(url-pattern=" /login ")
public class LoginServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * 如果用户没有登录就即没有在index.jsp页面登录就会跳转到这个方法 */ request.getRequestDispatcher("/login.jsp").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String userName = request.getParameter("username"); String passWord = request.getParameter("password"); String emsg = null; Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord); try { subject.login(token); } catch (UnknownAccountException e) { emsg = "用户名错误"; } catch (IncorrectCredentialsException e) { emsg = "密码错误"; } if (emsg != null) { // 说明认证错误 request.setAttribute("emsg", emsg); request.getRequestDispatcher("/login.jsp").forward(request, response); } else { request.getRequestDispatcher("/index.jsp").forward(request, response); } } }
- MyRealm.java
public class MyRealm extends AuthorizingRealm { UserDao userDao = new UserDao(); /** * 为当前登录的用户授予角色和权限 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String userName=principals.getPrimaryPrincipal().toString(); /** * 根据用户名获取当前用户的角色和权限集合 */ Set<String> roles=userDao.getRolesByName(userName); Set<String> objectPermissions=userDao.getPermissionsByName(userName); /** * 为该用户设置角色和权限 */ SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo(); authorizationInfo.addRoles(roles); authorizationInfo.setStringPermissions(objectPermissions); return authorizationInfo; } /** * 验证当前登录的用户 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String userName = token.getPrincipal().toString(); User user = userDao.getUserByName(userName); if (user != null) { /* * 说明用户登录成功 */ AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName(), user.getPassWord(), getName()); return authenticationInfo; } return null; } }
- UserDao.java
package com.shyroke.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.HashSet; import java.util.Set; import com.shyroke.entity.User; import com.shyroke.util.DBUtil; public class UserDao { /** * 根据用户名查询用户 * * @param userName * @return User */ public User getUserByName(String userName) { User user = null; Connection conn = null; PreparedStatement ps = null; String sql = ""; ResultSet rs = null; try { sql = "select * from user where user_name='" + userName + "'"; conn = DBUtil.getConn(); ps = conn.prepareStatement(sql); rs = ps.executeQuery(); if (rs.next()) { user=new User(); user.setId(rs.getInt("user_id")); user.setUserName(rs.getString("user_name")); user.setPassWord(rs.getString("user_password")); } } catch (Exception e) { e.printStackTrace(); } finally { try { DBUtil.close(conn, ps, rs); } catch (Exception e) { e.printStackTrace(); } } return user; } public Set<String> getRolesByName(String userName) { Set<String> roles = new HashSet<String>(); Connection conn = null; PreparedStatement ps = null; StringBuffer sb = new StringBuffer(); ResultSet rs = null; try { sb.append("select role_name from role where role_id in"); sb.append("("); sb.append("select role_id from user_role where user_id in("); sb.append("select user_id from user where user_name='" + userName + "')"); sb.append(")"); conn = DBUtil.getConn(); ps = conn.prepareStatement(sb.toString()); rs = ps.executeQuery(); while (rs.next()) { roles.add(rs.getString("role_name")); } } catch (Exception e) { e.printStackTrace(); } finally { try { DBUtil.close(conn, ps, rs); } catch (Exception e) { e.printStackTrace(); } } return roles; } public Set<String> getPermissionsByName(String userName) { Set<String> perms = new HashSet<String>(); Connection conn = null; PreparedStatement ps = null; StringBuffer sb = new StringBuffer(); ResultSet rs = null; try { sb.append("select permission_name from permission where permission_id in("); sb.append("select permission_id from permission_role where role_id in"); sb.append("("); sb.append("select role_id from user_role where user_id in"); sb.append(" ("); sb.append(" select user_id from user where user_name='"+userName+"'"); sb.append(" )"); sb.append(" )"); sb.append(" )"); conn = DBUtil.getConn(); ps = conn.prepareStatement(sb.toString()); rs = ps.executeQuery(); while (rs.next()) { perms.add(rs.getString("permission_name")); } } catch (Exception e) { e.printStackTrace(); } finally { try { DBUtil.close(conn, ps, rs); } catch (Exception e) { e.printStackTrace(); } } return perms; } }
- user.java
public class User { private Integer id; private String userName; private String passWord; //省略getset方法 }
- DBUtil.java
public class DBUtil { private static final String DRIVER = "com.mysql.jdbc.Driver"; private static final String USER = "root"; private static final String PASSWD = ""; private static final String URL = "jdbc:mysql://127.0.0.1:3306/shiro?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"; private static ComboPooledDataSource dataSource = null; static { try { Class.forName(DRIVER); Context context = new InitialContext(); dataSource = new ComboPooledDataSource(); dataSource.setMaxPoolSize(50); dataSource.setInitialPoolSize(20); dataSource.setJdbcUrl(URL); dataSource.setDriverClass(DRIVER); dataSource.setUser(USER); dataSource.setPassword(PASSWD); } catch (Exception e) { throw new RuntimeException("驱动包加载故障"); } } public static Connection getConn() { Connection conn = null; try { conn = dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return conn; } public static void close(Connection con,PreparedStatement ps,ResultSet rs)throws Exception{ if(con!=null){ con.close(); } if(ps!=null){ ps.close(); } if(rs!=null){ rs.close(); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(DBUtil.getConn() + "\t " + i); } } }
- 目录结构
- 结果:
- 本例代码: here