目录结构:

 数据库结构:

一·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_web</display-name>
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<context-param>
<param-name>shiroEnvironmentClass</param-name>
<param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value>
</context-param>
<context-param>
<param-name>shiroConfigLocations</param-name>
<param-value>classpath:shiro.ini</param-value>
</context-param>
<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>
</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 Set<String> listRoles(String userName) { Set<String> 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<String> listPermissions(String userName) {
Set<String> 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();
Set<String> permissions = new Dao().listPermissions(userName);
Set<String> 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 here</title>
</head>
<body>
<div class="workingroom">
<div class="loginDiv">
<c:if test="${empty subject.principal }">
<a href="login.jsp">login</a><br>
</c:if>
<c:if test="${!empty subject.principal }">
<span class="desc">hello,${subject.principal }!</span><br>
<a href="doLogout">logout</a>
</c:if>
<br>
<a href="listProduct.jsp">query product</a><span class="desc">(登录后才能查看)</span><br>
<a href="deleteProduct.jsp">delete product</a><span class="desc">(需要产品管理员角色)</span><br>
<a href="deleteOrder.jsp">delete order</a><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 here</title>
</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 角色:admin</span><br>
<span class="desc">账号:li4 密码:abcde 角色:productManager</span><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 here</title>
</head>
<body>
<div class="workingroom">
listProduct.jsp ,能进来,就表示已经登录成功了
<br>
<a href="#" onclick="javascript:history.back()">return</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 here</title>
</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 here</title>
</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 here</title>
</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 here</title>
</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

shiro实战(1)--web的更多相关文章

  1. Shiro实战教程-刘志敏-专题视频课程

    Shiro实战教程-62人已学习 课程介绍        本教程只介绍基本的 Shiro 使用,不会过多分析源码等,重在使用. 适用人群: 1.了解基于Servlet进行Web应用开发 2.了解Spr ...

  2. 自学Zabbix4.3 zabbix实战监控Web网站性能

    自学Zabbix4.3 zabbix实战监控Web网站性能 用zabbix如何监控web性能和可用性呢?一般分为四个步骤:打开网站.登陆.登陆验证.退出,看实例. 1. 检测流程 1. 打开网站:如果 ...

  3. Apache Shiro:【1】Shiro基础及Web集成

    Apache Shiro:[1]Shiro基础及Web集成 Apache Shiro是什么 Apache Shiro是一个强大且易于使用的Java安全框架,提供了认证.授权.加密.会话管理,与spri ...

  4. Spring Boot集成Shiro实战

    Spring Boot集成Shiro权限验证框架,可参考: https://shiro.apache.org/spring-boot.html 引入依赖 <dependency> < ...

  5. 从0到1实战移动Web App开发

    从0到1实战移动Web App开发   教程介绍 从0到1 实战webapp,通过热门的web前端技术实现移动端app应用,先基础.后实战,在讲解的同时引导思考,会抛出自己独特的观点,一行一行写代码讲 ...

  6. shiro实战系列(九)之Web

    一.Configuration(配置) 将 Shiro 集成到任何 Web 应用程序的最简单的方法是在 web.xml 中配置 ContextListener 和 Filter,理解如何读取 Shir ...

  7. shiro实战系列(二)之入门实战续

    下面讲解基于实战系列一,所以相关的java文件获取pom.xml及其log4j文件同样适用于本次讲解. 一.Using Shiro Using Shiro 现在我们的 SecurityManager ...

  8. shiro实战系列(一)之入门实战

    一.什么是shiro? Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密.   Apache Shiro 的首要目标是易于使用和理解.安全有 ...

  9. Springmvc+Shiro实战

    原文链接:http://blog.csdn.net/qq_37936542/article/details/79010449 springmvc+shiro实现系统粗细粒度的权限管理步骤: 1:表格设 ...

随机推荐

  1. Centos Linux下使用Metasploit渗透android

    .newline{display:block}.katex .base{position:relative;white-space:nowrap;width:min-content}.katex .b ...

  2. vue中computed(计算属性)和watch在实现父子组件props同步时的实际区分

    vue中computed和watch的对比是一个很有意思的话题. 看过官网教程以后,我们往往更倾向多使用computed.computed优点很多,却在某些时候不太适用. 今天我们就稍微讨论一下,当我 ...

  3. 挑战10个最难的Java面试题(附答案)【上】

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),验证通过后,输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动&quo ...

  4. Maven学习整理

    1. window系统中安装Maven 2. 解决使用代理联网时无法下载jar包 3. 配置本地仓库 4. 处理本地仓库和中央仓库都没有依赖的jar包的情况

  5. git 使用详解(9)-- 分支的新建与合并 git branch -d、merge、 --merged/--no-merged/-v

    现在让我们来看一个简单的分支与合并的例子,实际工作中大体也会用到这样的工作流程: 开发某个网站. 为实现某个新的需求,创建一个分支. 在这个分支上开展工作. 假设此时,你突然接到一个电话说有个很严重的 ...

  6. Java修炼——接口详解_接口的特征_使用接口的意义

    接口中可以包含的内容: 抽象法和非抽象方法(jdk1.8,必须使用default的关键字),属性(public static final)常量. 接口和类的关系 1.(继承了接口)类必须去实现接口中的 ...

  7. 学习go第一天-编写第一个go程序

    开发环境构建 GOPATH 在1.8版本前必须设置这个环境变量 1.8以及更高版本如果没有设置,则使用默认值在Mac上GOPATH可以通过修改 -/.bash_profile来设置 程序基本结构 pa ...

  8. HDU5919 Sequence II(主席树)

    Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,⋯,ana1,a2,⋯,anThere are ...

  9. Java构造器浅析

    Java构造器 问题引出 1.先看一段简单创建对象的例子: public class constructTest { public static void main(String[] args) { ...

  10. 服务网格数据平面的关键:层层剖析Envoy配置

    Envoy是一种高性能C++分布式代理,专为单个服务和应用程序设计.作为Service Mesh中的重要组件,充分理解其配置就显得尤为重要.本文列出了使用Envoy而不用其他代理的原因.并给出了Env ...