4.0.0 com.qfedu Days62Shiro02Web 1.0-SNAPSHOT war 8 8 junit junit 4.12 test org.apache.shiro shiro-web 1.3.2 mysql mysql-connector-java 8.0.24 com.mchange c3p0 0.9.5.2 commons-logging commons-logging 1.2 javax.servlet javax.servlet-api 3.1.0 provided javax.servlet.jsp jsp-api 2.2 provided jstl jstl 1.2 org.projectlombok lombok 1.18.16 provided org.apache.maven.plugins maven-compiler-plugin 3.6.1 1.8 org.apache.tomcat.maven tomcat7-maven-plugin 2.2 / 8080
web.xml配置shiro
org.apache.shiro.web.env.EnvironmentLoaderListener ShiroFilter org.apache.shiro.web.servlet.ShiroFilter ShiroFilter /* 401 /errorpage.jsp
说明: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 + "---------------"); Listroles = ius.getRolesByUserName(username); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Roles r : roles) { info.addRole(r.getRname()); } List 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) throwsAuthenticationException { 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); ListgetRolesByUserName(String username); List 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 ListgetRolesByUserName(String username) { return iud.getRolesByUsername(username); } @Override public List 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); ListgetRolesByUsername(String username); List 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 ListgetRolesByUsername(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 = 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 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 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';
调用流程
完成