Shiro提供了与Web集成的支持,其通过一个ShiroFilter入口来拦截需要安全控制的URL,然后进行相应的控制,ShiroFilter类似于如Struts2/SpringMVC这种web框架的前端控制器,其是安全控制的入口点,其负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作。
使用maven来搭建shiro+serlvet授权
(1)pom.xml文件
<!-- 添加servlet支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- jstl支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- log4j日志支持 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!--slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- shiro 包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
(2)通过查看官网如何配置web.xml文件
如果shiro.ini文件没有配置,则默认会去src/main/webapp/WEB-INF/这个目录下寻找shiro.ini这个文件.
<!-- (1)shiro监听器 -->
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<!--(2)shiroFilter过滤 -->
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
<!-- 初始化参数 :配置在src/main/resources目录下-->
<init-param>
<param-name>configPath</param-name>
<param-value>classpath:shiro.ini</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(3)shiro.ini文件(可以查看官网文档)
[main]
#身份认证,角色,权限
authc.loginUrl=/login #loginUrl是属性(FormAuthenticationFilter)
roles.unauthorizedUrl=/unauthorized.jsp #unauthorizedUrl是属性在RolesAuthorizationFilter
perms.unauthorizedUrl=/unauthorized.jsp #unauthorizedUrl同上
[users]
#用户有着对应的角色
mike=123456,admin
jack=aaa,teacher
json=012
[roles]
#角色
admin=user:*
teacher=student:*
[urls]
#访问的地址的权限
/login=anon #匿名访问
/admin=authc #需要认证
/student=roles[teacher] #必须要有这个角色才能访问
/teacher=perms["user:create"] 必须拥有这个权限才能访问
(4)jsp登录页面
<form action="login" method="post">
userName:<input name="userName" />
<p />
password:<input type="password" name="password" />
<p />
<input type="submit" value="login" />
</form>
(5)创建LoginServlet用来测试身份验证
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("LoginServlet doPost!");
// 输出对象
PrintWriter out = response.getWriter();
//获得请求参数
String userName=request.getParameter("userName");
String password=request.getParameter("password");
//获得当前用户对象
Subject currentUser=SecurityUtils.getSubject();
//获得令牌
UsernamePasswordToken token=new UsernamePasswordToken(userName, password);
try {
//登录
currentUser.login(token);
//跳转
response.sendRedirect("ok.jsp");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
request.setAttribute("msg", "用户名或密码错误!");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
out.flush();
out.close();
}
(6)创建AdminServlet用来测试角色和权限
@WebServlet(name = "AdminServlet", urlPatterns = { "/admin","/student","/teacher"})
public class AdminServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// org.apache.shiro.web.filter.authc.FormAuthenticationFilter
// org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
/**
* @see HttpServlet#HttpServlet()
*/
public AdminServlet() {
// System.out.println("constructure LoginServlet");
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
//获得路径
String path=request.getServletPath();
String methodName=path.substring(1);
System.out.println(path+"-->"+methodName);
//反射机制
try {
Method method=getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
//调用
method.invoke(this, request,response);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.flush();
out.close();
}
protected void admin(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("AdminServlet Admin!");
System.out.println("access Admin!");
out.flush();
out.close();
}
protected void student(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("AdminServlet Student!");
out.flush();
out.close();
}
protected void teacher(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("AdminServlet Teacher!");
out.flush();
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("AdminServlet doPost!");
}
}
运行测试:
(a)用mike用户访问,能访问/admin哦
(b)用jack用户访问,能访问/student,/teacher哦
(c)用json用户访问,不能访问/student哦
注意:
url模式使用Ant风格模式
Ant路径通配符支持?、*、**,注意通配符匹配不包括目录分隔符“/”:
?:匹配一个字符,如”/admin?”将匹配/admin1,/admin2 ..,但不匹配/admin或/admin12;
*:匹配零个或多个字符串,如/admin*将匹配/admin、/admin123,但不匹配/admin/1;
**:匹配路径中的零个或多个路径,如/admin/**将匹配/admin/a或/admin/a
admin1 /admin2 /admin3....
可以访问: http://localhost:8888/shiroweb/admin12
可以访问: http://localhost:8888/shiroweb/admin/admin
Jsp标签授权
jsp页面导入<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
Guest 标签:用户没有身份验证时显示相应信息,即游客访问信息;
User 标签:用户已经身份验证/记住我登录后显示相应的信息;
Authenticated 标签:用户已经身份验证通过,即 Subject.login 登录成功,不是记住我登录的。
notAuthenticated 标签:用户没有身份验证通过,即没有调用 Subject.login 进行登录,包括记住我自动登录
的也属于未进行身份验证。
principal 标签 显示用户身份信息,默认调用 Subject.getPrincipal()获取,即 Primary Principal。
hasRole 标签 如果当前 Subject 有角色将显示 body 体内容。
lacksRole 标签 如果当前 Subject 没有角色将显示 body 体内容。
hasAnyRoles 标签 如果当前 Subject 有任意一个角色(或的关系)将显示 body 体内容。
hasPermission 标签 如果当前 Subject 有权限将显示 body 体内容。
lacksPermission 标签 如果当前 Subject 没有权限将显示 body 体内容。
登录成功ok.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>欢迎您</h1>
<shiro:hasRole name="admin">
admin角色用户 <shiro:principal/>
</shiro:hasRole>
<shiro:hasPermission name="student:create">
student:create权限的用户 <shiro:principal/>
</shiro:hasPermission>
</body>
mike用户登录
jack用户登录