目录结构:
数据库结构:
一·web.xml
xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>shiro_webdisplay-name> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListenerlistener-class> listener> <context-param> <param-name>shiroEnvironmentClassparam-name> <param-value>org.apache.shiro.web.env.IniWebEnvironmentparam-value> context-param> <context-param> <param-name>shiroConfigLocationsparam-name> <param-value>classpath:shiro.iniparam-value> context-param> <filter> <filter-name>shiroFilterfilter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilterfilter-class> filter> <filter-mapping> <filter-name>shiroFilterfilter-name> <url-pattern>/*url-pattern> filter-mapping> web-app>
二·shiro.ini
[main]
#使用数据库验证授权
databaseRealm=com.yuanbo.DatabaseRealm
securityManager.realms=$databaseRealm
#配置一个url拥有多个role
roles=com.yuanbo.CustomRolesAuthorizationFilter
#没有验证的情况
authc.loginUrl=/login.jsp
#没有角色的情况
roles.unauthorizedUrl=/noRoles.jsp
#没有权限的情况
perms.unauthorizedUrl=/noPerms.jsp
#数据库中取得,不需要配置
[users]
[urls]
/doLogout=logout
#可以匿名访问
/login.jsp=anon
/noRoles.jsp=anon
/noPerms.jsp=anon
#登录后才能查看
/listProduct.jsp=authc
/deleteProduct.jsp=authc,roles[admin,productManager]
/deleteOrder.jsp=authc,perms["deleteOrder"]
三·实体类
package com.yuanbo; public class User { private int id; private String name; private String password; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
四·DB
package com.yuanbo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; import java.util.Set; public class Dao { public Dao() { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/shiro?serverTimezone=UTC", "root", "123456"); } public String getPassword(String userName) { String sql = "select password from user where name = ?"; try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { ps.setString(1, userName); ResultSet rs = ps.executeQuery(); if (rs.next()) return rs.getString("password"); } catch (SQLException e) { e.printStackTrace(); } return null; } public SetlistRoles(String userName) { Set roles = new HashSet<>(); String sql = "select r.name from user u " + "left join user_role ur on u.id = ur.uid " + "left join Role r on r.id = ur.rid " + "where u.name = ?"; try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { ps.setString(1, userName); ResultSet rs = ps.executeQuery(); while (rs.next()) { roles.add(rs.getString(1)); } } catch (SQLException e) { e.printStackTrace(); } return roles; } public Set listPermissions(String userName) { Set permissions = new HashSet<>(); String sql = "select p.name from user u " + "left join user_role ru on u.id = ru.uid " + "left join role r on r.id = ru.rid " + "left join role_permission rp on r.id = rp.rid " + "left join permission p on p.id = rp.pid " + "where u.name =?"; try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) { ps.setString(1, userName); ResultSet rs = ps.executeQuery(); while (rs.next()) { permissions.add(rs.getString(1)); } } catch (SQLException e) { e.printStackTrace(); } return permissions; } public static void main(String[] args) { System.out.println(new Dao().listRoles("zhang3")); System.out.println(new Dao().listRoles("li4")); System.out.println(new Dao().listPermissions("zhang3")); System.out.println(new Dao().listPermissions("li4")); } }
五·realm
package com.yuanbo; import java.util.Set; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class DatabaseRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String userName = (String) principalCollection.getPrimaryPrincipal(); Setpermissions = new Dao().listPermissions(userName); Set roles = new Dao().listRoles(userName); SimpleAuthorizationInfo s = new SimpleAuthorizationInfo(); s.setStringPermissions(permissions); s.setRoles(roles); return s; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken t = (UsernamePasswordToken) token; //String userName = token.getPrincipal().toString(); String userName =new String(t.getUsername()); String password = new String(t.getPassword()); String passwordInDB = new Dao().getPassword(userName); if(passwordInDB == null || !passwordInDB.equals(password)) throw new AuthenticationException(); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName,password,getName()); return info; } }
六·过滤器(一个url多个roles访问)
package com.yuanbo; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.authz.AuthorizationFilter; public class CustomRolesAuthorizationFilter extends AuthorizationFilter { @Override protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception { Subject subject = getSubject(req, resp); String[] rolesArray = (String[]) mappedValue; if (rolesArray == null || rolesArray.length == 0) { //没有角色限制,有权限访问 return true; } for (int i = 0; i < rolesArray.length; i++) { if (subject.hasRole(rolesArray[i])) { //若当前用户是rolesArray中的任何一个,则有权限访问 return true; } } return false; } }
七·servlet
package com.yuanbo; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; /** * Servlet implementation class LoginServlet */ @WebServlet(name = "loginServlet", urlPatterns = "/login") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter("userName"); String password = request.getParameter("password"); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(userName, password); try { subject.login(token); Session session = subject.getSession(); session.setAttribute("subject", subject); response.sendRedirect("index.jsp"); } catch (AuthenticationException e) { request.setAttribute("error","验证失败"); request.getRequestDispatcher("login.jsp").forward(request, response); } } }
八·index.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> <link rel="stylesheet" type="text/css" href="static/css/style.css"/> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title heretitle> head> <body> <div class="workingroom"> <div class="loginDiv"> <c:if test="${empty subject.principal }"> <a href="login.jsp">logina><br> c:if> <c:if test="${!empty subject.principal }"> <span class="desc">hello,${subject.principal }!span><br> <a href="doLogout">logouta> c:if> <br> <a href="listProduct.jsp">query producta><span class="desc">(登录后才能查看)span><br> <a href="deleteProduct.jsp">delete producta><span class="desc">(需要产品管理员角色)span><br> <a href="deleteOrder.jsp">delete ordera><span class="desc">(需要删除订单权限)span><br> div> div> body> html>
九·login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <html> <link rel="stylesheet" type="text/css" href="static/css/style.css" /> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title heretitle> head> <body> <div class="workingroom"> <div class="errorInfo">${error }div> <form action="login" method="post"> account: <input type="text" name="userName" /><br> password: <input type="password" name="password"/><br> <br> <input type="submit" value="login"> <div> <span class="desc">账号:zhang3 密码:12345 角色:adminspan><br> <span class="desc">账号:li4 密码:abcde 角色:productManagerspan><br> div> form> div> body> html>
十
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> <link rel="stylesheet" type="text/css" href="static/css/style.css" /> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title heretitle> head> <body> <div class="workingroom"> listProduct.jsp ,能进来,就表示已经登录成功了 <br> <a href="#" onclick="javascript:history.back()">returna> div> body> html>
十一
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> <link rel="stylesheet" type="text/css" href="static/css/style.css" /> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title heretitle> head> <body> <div class="workingroom"> deleteProduct.jsp,能进来<br>就表示拥有 productManager 角色 <br> <a href="#" onClick="javascript:history.back()">返回a> div> body> html>
十二
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> <link rel="stylesheet" type="text/css" href="static/css/style.css" /> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title heretitle> head> <body> <div class="workingroom"> deleteOrder.jsp ,能进来,就表示有deleteOrder权限 <br> <a href="#" onClick="javascript:history.back()">返回a> div> body> html>
十三
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> <link rel="stylesheet" type="text/css" href="static/css/style.css" /> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title heretitle> head> <body> <div class="workingroom"> 权限不足 <br> <a href="#" onClick="javascript:history.back()">返回a> div> body> html>
十四
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html> <link rel="stylesheet" type="text/css" href="static/css/style.css" /> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title heretitle> head> <body> <div class="workingroom"> 角色不匹配 <br> <a href="#" onClick="javascript:history.back()">返回a> div> body> html>
最后,推荐一个java学习平台吧,感觉挺不错的,写得挺细的,还有问答,可以解疑
https://how2j.cn/k/shiro/shiro-web/1722.html?p=81485