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 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 + "---------------");
List roles = 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);
List getRolesByUserName(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 List getRolesByUserName(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);
List getRolesByUsername(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 List 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 = 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'; 调用流程
完成