shiro与web的整合
-
pom文件添加依赖
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.qfedu</groupId> <artifactId>Days62Shiro02Web</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.24</version> </dependency> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <!-- define the project compile level --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <!-- 添加tomcat插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/</path> <port>8080</port> </configuration> </plugin> </plugins> </build> </project>
-
web.xml配置shiro
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <error-page> <error-code>401</error-code> <location>/errorpage.jsp</location> </error-page> </web-app>
说明:EnvironmentLoaderListener里面包含了SecurityManager对象和ServletContext当中注册shiro, ShiroFilter让所有的请求都经过ShiroFilter过滤器
-
classpath下的shiro.ini文件
[main] mr=com.qfedu.shiro.MyRealm authc=org.apache.shiro.web.filter.authc.FormAuthenticationFilter authc.loginUrl=/login.jsp securityManager.realm=$mr [urls] /index.html = anon #/user/create = anon #/user/** = authc #/admin/** = authc, roles[administrator] #/rest/** = authc, rest #/remoting/rpc/** = authc, perms["remote:invoke"] /superManager.jsp=authc, roles[super manager] /manager.jsp=authc, roles[manager] /guest.jsp=authc, roles[guest] /select.jsp=authc, perms[select] /save.jsp=authc, perms[save] /delete.jsp=authc, perms[delete] /update.jsp=authc, perms[update]
authc代表认证用户, roles[xxx]代表拥有xxx角色的用户, perms[xxx]代表拥有xxx权限的用户, anon匿名用户
-
UserServlet
package com.qfedu.controller; import com.qfedu.pojo.Users; import com.qfedu.service.IUserService; import com.qfedu.service.impl.UserServiceImpl; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet(name = "UserServlet", value = "/UserServlet") public class UserServlet extends HttpServlet { private IUserService ius = new UserServiceImpl(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); // /shiro的调用/ // IniSecurityManagerFactory()默认加载shiro.ini文件 IniSecurityManagerFactory factory = new IniSecurityManagerFactory(); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { // 登录功能,真正实现用户的认证功能 subject.login(token); System.out.println(subject.isAuthenticated()); // System.out.println(subject.hasRole("manager")); // // subject.checkPermissions("select", "update"); response.sendRedirect("success.jsp"); } catch (AuthenticationException e) { e.printStackTrace(); } // // Users u = ius.login(username, password); // // if(u != null){ // request.getRequestDispatcher("success.jsp").forward(request,response); // } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
-
MyRealm
package com.qfedu.shiro; import com.qfedu.pojo.Perms; import com.qfedu.pojo.Roles; import com.qfedu.pojo.Users; import com.qfedu.service.IUserService; import com.qfedu.service.impl.UserServiceImpl; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import java.util.List; public class MyRealm extends AuthorizingRealm { private IUserService ius = new UserServiceImpl(); /** * 授权方法,含有的参数是身份集合,使用身份集合就可以获取用户账户信息 * * @param principalCollection * @return AuthorizationInfo接口对象 * 剩余的事情就交给了shiro的会话管理器来自动完成 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String username = getAvailablePrincipal(principalCollection).toString(); System.out.println(username + "---------------"); List<Roles> roles = ius.getRolesByUserName(username); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Roles r : roles) { info.addRole(r.getRname()); } List<Perms> perms = ius.getPermsByUserName(username); for (Perms p : perms) { info.addStringPermission(p.getPname()); } return info; } /** * 认证方法,用户在输入了自己的用户名和密码信息之后,点击提交按钮,即通过subject的login(token)方法, * 将请求传递给当前方法,进行认证的处理 * @param authenticationToken,含有用户名和密码参数的token对象,可以获取到用户名(身份)和密码(凭证)信息 * @return AuthenticationInfo接口对象 * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String username = token.getUsername(); char[] passchar = token.getPassword(); // 为了保证密码的安全性,java几乎将密码都设置成立字符数组 String password = new String(passchar); System.out.println(username + "\t" + password); Users u = ius.login(username, password); if(u != null){ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName()); return info; } return null; } }
以前传统方式是controller->service->dao,dao与数据库交互完成crud功能,返回给dao,返回给service,返回给controller
shiro与web的整合,则是controller->shiro->service->dao
-
IUserService.java
package com.qfedu.service; import com.qfedu.pojo.Perms; import com.qfedu.pojo.Roles; import com.qfedu.pojo.Users; import java.util.List; public interface IUserService { Users login(String username, String password); List<Roles> getRolesByUserName(String username); List<Perms> getPermsByUserName(String username); }
-
UserServiceImpl.java
package com.qfedu.service.impl; import com.qfedu.dao.IUserDao; import com.qfedu.dao.impl.UserDaoImpl; import com.qfedu.pojo.Perms; import com.qfedu.pojo.Roles; import com.qfedu.pojo.Users; import com.qfedu.service.IUserService; import java.util.List; public class UserServiceImpl implements IUserService { private IUserDao iud = new UserDaoImpl(); @Override public Users login(String username, String password) { return iud.login(username, password); } @Override public List<Roles> getRolesByUserName(String username) { return iud.getRolesByUsername(username); } @Override public List<Perms> getPermsByUserName(String username) { return iud.getPermsByUsername(username); } }
-
IUserDao.java
package com.qfedu.dao; import com.qfedu.pojo.Perms; import com.qfedu.pojo.Roles; import com.qfedu.pojo.Users; import java.util.List; public interface IUserDao { Users login(String username, String password); List<Roles> getRolesByUsername(String username); List<Perms> getPermsByUsername(String username); }
-
UserDaoImpl.java
package com.qfedu.dao.impl; import com.qfedu.dao.IUserDao; import com.qfedu.pojo.Perms; import com.qfedu.pojo.Roles; import com.qfedu.pojo.Users; import com.qfedu.util.C3P0Util; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class UserDaoImpl implements IUserDao { private Connection conn = null; private PreparedStatement ptst = null; private ResultSet rs = null; @Override public Users login(String username, String password) { conn = C3P0Util.getConn(); String sql = "select * from users where username = ? and password =?"; try { ptst = conn.prepareStatement(sql); ptst.setString(1, username); ptst.setString(2, password); rs = ptst.executeQuery(); if (rs.next()){ int uid = rs.getInt(1); String name = rs.getString(2); String pass = rs.getString(3); String tel = rs.getString(4); String addr = rs.getString(5); Users u = new Users(); u.setUid(uid); u.setUsername(name); u.setPassword(pass); u.setAddr(addr); u.setTel(tel); return u; } } catch (SQLException throwables) { throwables.printStackTrace(); } return null; } @Override public List<Roles> getRolesByUsername(String username) { conn = C3P0Util.getConn(); String sql = "select r.* from users u ,\n" + " user_role ur,\n" + " roles r\n" + " where u.uid = ur.uid and ur.rid = r.rid\n" + " and username = ?"; try { ptst = conn.prepareStatement(sql); ptst.setString(1, username); rs = ptst.executeQuery(); List<Roles> roles = new ArrayList<>(); while (rs.next()){ int rid = rs.getInt(1); String rname = rs.getString(2); String rdesc = rs.getString(3); Roles r = new Roles(); r.setRid(rid); r.setRname(rname); r.setRdesc(rdesc); roles.add(r); } return roles; } catch (SQLException throwables) { throwables.printStackTrace(); } return null; } @Override public List<Perms> getPermsByUsername(String username) { conn = C3P0Util.getConn(); String sql = "select distinct p.* from users u ,\n" + " user_role ur,\n" + " roles r,\n" + " role_perm rp,\n" + " perms p\n" + "where u.uid = ur.uid and ur.rid = r.rid\n" + " and r.rid = rp.rid and rp.pid = p.pid\n" + " and username = ?"; try { ptst = conn.prepareStatement(sql); ptst.setString(1, username); rs = ptst.executeQuery(); List<Perms> roles = new ArrayList<>(); while (rs.next()){ int rid = rs.getInt(1); String rname = rs.getString(2); String rdesc = rs.getString(3); Perms r = new Perms(); r.setPid(rid); r.setPname(rname); r.setPdesc(rdesc); roles.add(r); } return roles; } catch (SQLException throwables) { throwables.printStackTrace(); } return null; } }
-
C3P0Util.java
package com.qfedu.util; import com.mchange.v2.c3p0.ComboPooledDataSource; import java.beans.PropertyVetoException; import java.sql.*; public class C3P0Util { private final static String DB_URL = Env.getInstance().getProperty("url"); private final static String DB_DRIVER = Env.getInstance().getProperty("driver"); private final static String DB_USER = Env.getInstance().getProperty("user"); private final static String DB_PASS = Env.getInstance().getProperty("pass"); private static Connection conn = null; public static Connection getConn(){ try { ComboPooledDataSource ds = new ComboPooledDataSource(); ds.setJdbcUrl(DB_URL); ds.setDriverClass(DB_DRIVER); ds.setUser(DB_USER); ds.setPassword(DB_PASS); conn = ds.getConnection(); } catch (SQLException throwables) { throwables.printStackTrace(); } catch (PropertyVetoException e) { e.printStackTrace(); } return conn; } public static void closeAll(Connection conn, PreparedStatement ptst, ResultSet rs){ try { if(rs != null){ rs.close(); rs = null; } if(ptst != null){ ptst.close(); ptst = null; } if(conn != null){ conn.close(); conn = null; } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
-
Env.java
package com.qfedu.util; import java.io.IOException; import java.util.Properties; public class Env extends Properties { private static Env instance = null; private Env(){ try { load(getClass().getResourceAsStream("/db.properties")); } catch (IOException e) { e.printStackTrace(); } } public static Env getInstance(){ if (instance == null){ instance = new Env(); } return instance; } }
-
db.properties
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/rbac2206?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8 user=java2206 pass=123456
-
rbac设计
create database rbac2206; use rbac2206; create table users( uid int primary key auto_increment, username varchar(20) not null unique, password varchar(20) not null, tel varchar(11), addr varchar(30) ); create table roles( rid int primary key auto_increment, rname varchar(20) not null unique , rdesc varchar(20) ); create table perms( pid int primary key auto_increment, pname varchar(20) not null unique, pdesc varchar(20) ); insert into users values(null, 'wukong', '888888', '188888888', 'huaguoshan'); insert into users values(null, 'wuneng', '777777', '177777777', 'gaolaozhuang'); insert into users values(null, 'wujing', '666666', '166666666', 'liushahe'); insert into users values(null, 'tangtang', '000000', '100000', 'changan'); insert into roles values(null, 'manager', 'manager desc'); insert into roles values(null, 'super manager', 'super manager desc'); insert into roles values(null, 'guest', 'guest desc'); insert into perms values(null, 'select', 'select desc'); insert into perms values(null, 'save', 'save desc'); insert into perms values(null, 'delete', 'delete desc'); insert into perms values(null, 'update', 'update desc'); create table user_role( uid int, rid int, primary key(uid, rid) ); create table role_perm( rid int, pid int, primary key(rid, pid) ); insert into user_role values(4, 1); insert into user_role values(4, 2); insert into user_role values(4, 3); insert into user_role values(1, 1); insert into user_role values(1, 3); insert into user_role values(2, 3); insert into user_role values(3, 3); insert into role_perm values(2, 1); insert into role_perm values(2, 2); insert into role_perm values(2, 3); insert into role_perm values(2, 4); insert into role_perm values(1, 1); insert into role_perm values(1, 4); insert into role_perm values(3, 1); select username, password, addr, tel, rname, rdesc, pname, pdesc from users u, roles r, perms p, user_role ur, role_perm rp where u.uid = ur.uid and r.rid = ur.rid and p.pid = rp.pid and ur.rid = rp.rid order by username; select r.* from users u , user_role ur, roles r where u.uid = ur.uid and ur.rid = r.rid and username = 'tangtang'; select distinct p.* from users u , user_role ur, roles r, role_perm rp, perms p where u.uid = ur.uid and ur.rid = r.rid and r.rid = rp.rid and rp.pid = p.pid and username = 'wuneng';