(五)shiro-web

shiro主要用于web开发环境下,本小节学习web环境下的应用

1.准备工作

添加jar包,先前都是添加的core包,web环境下需要shiro-web,同时为了便于开发,同时还需要servlet,jsp等jar包

	<!-- javax.servlet-api -->
	<dependency>
    	<groupId>javax.servlet</groupId>
    	<artifactId>javax.servlet-api</artifactId>
    	<version>3.1.0</version>
	</dependency>

  <!-- javax.servlet.jsp-api -->
	<dependency>
    	<groupId>javax.servlet.jsp</groupId>
    	<artifactId>javax.servlet.jsp-api</artifactId>
    	<version>2.3.1</version>
	</dependency>
  
  <!-- javax.servlet/jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

<!-- shiro-core -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.3.2</version>
</dependency>

<!-- shiro-web -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
    <version>1.3.2</version>
</dependency>

    <!-- commons-logging -->
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
    
      <!-- slf4j-log4j12 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
</dependency>

<!-- log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

同时还需要添加log4j的配置文件


2.启动shiro

web环境下初始化shiro,需要在web.xml文件中添加拦截器和监听器

<listener>
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
  
    <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>

同时还需要添加shiro的配置文件:shiro.ini,文件路径可以:1./WEB-INF/shiro.ini 或者 2. 根目录下

如果没有配置文件,启动就会报错。

扫描二维码关注公众号,回复: 5682449 查看本文章

自定义路径:

<filter>
    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class>
    <init-param>
        <param-name>configPath</param-name>
        <param-value>/WEB-INF/anotherFile.ini</param-value>
    </init-param>
</filter>
修改
<param-value>/WEB-INF/anotherFile.ini</param-value>

可以自定义路径

详情可见http://shiro.apache.org/web.html#Web-RememberMeServices


3.web下INI配置

ini配置文件中有四个部分:[main]、[users]、[roles]、[urls]

[urls]为应用程序中任何匹配的URL定义自定义的过滤器

例子;

[urls]

/index.html = anon
/user/create = anon
/user/** = authc
/admin/** = authc, roles[administrator]
/rest/** = authc, rest
/remoting/rpc/** = authc, perms["remote:invoke"]
等号左边的是要拦截的URL,等号右边则是过滤器

shiro的过滤器支持自定义过滤器,通过自己定义的过滤器java代码,在ini配置文件中声明。

可以参考http://jinnianshilongnian.iteye.com/blog/2025656

这里主要讲shiro提供的默认过滤器

参考于http://jinnianshilongnian.iteye.com/blog/2025656

Shiro内置了很多默认的拦截器,比如身份验证、授权等相关的。默认拦截器可以参考org.apache.shiro.web.filter.mgt.DefaultFilter中的枚举拦截器:  

默认拦截器名

拦截器类

说明(括号里的表示默认值)

身份验证相关的

authc

org.apache.shiro.web.filter.authc

.FormAuthenticationFilter

基于表单的拦截器;如“/**=authc”,如果没有登录会跳到相应的登录页面登录;主要属性:usernameParam:表单提交的用户名参数名( username);  passwordParam:表单提交的密码参数名(password); rememberMeParam:表单提交的密码参数名(rememberMe);  loginUrl:登录页面地址(/login.jsp);successUrl:登录成功后的默认重定向地址; failureKeyAttribute:登录失败后错误信息存储key(shiroLoginFailure);

authcBasic

org.apache.shiro.web.filter.authc

.BasicHttpAuthenticationFilter

Basic HTTP身份验证拦截器,主要属性: applicationName:弹出登录框显示的信息(application);

logout

org.apache.shiro.web.filter.authc

.LogoutFilter

退出拦截器,主要属性:redirectUrl:退出成功后重定向的地址(/);示例“/logout=logout”

user

org.apache.shiro.web.filter.authc

.UserFilter

用户拦截器,用户已经身份验证/记住我登录的都可;示例“/**=user”

anon

org.apache.shiro.web.filter.authc

.AnonymousFilter

匿名拦截器,即不需要登录即可访问;一般用于静态资源过滤;示例“/static/**=anon”

授权相关的

roles

org.apache.shiro.web.filter.authz

.RolesAuthorizationFilter

角色授权拦截器,验证用户是否拥有所有角色;主要属性: loginUrl:登录页面地址(/login.jsp);unauthorizedUrl:未授权后重定向的地址;示例“/admin/**=roles[admin]”

perms

org.apache.shiro.web.filter.authz

.PermissionsAuthorizationFilter

权限授权拦截器,验证用户是否拥有所有权限;属性和roles一样;示例“/user/**=perms["user:create"]”

port

org.apache.shiro.web.filter.authz

.PortFilter

端口拦截器,主要属性:port(80):可以通过的端口;示例“/test= port[80]”,如果用户访问该页面是非80,将自动将请求端口改为80并重定向到该80端口,其他路径/参数等都一样

rest

org.apache.shiro.web.filter.authz

.HttpMethodPermissionFilter

rest风格拦截器,自动根据请求方法构建权限字符串(GET=read, POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read, MKCOL=create)构建权限字符串;示例“/users=rest[user]”,会自动拼出“user:read,user:create,user:update,user:delete”权限字符串进行权限匹配(所有都得匹配,isPermittedAll);

ssl

org.apache.shiro.web.filter.authz

.SslFilter

SSL拦截器,只有请求协议是https才能通过;否则自动跳转会https端口(443);其他和port拦截器一样;

其他

noSessionCreation

org.apache.shiro.web.filter.session

.NoSessionCreationFilter

不创建会话拦截器,调用 subject.getSession(false)不会有什么问题,但是如果 subject.getSession(true)将抛出 DisabledSessionException异常;


定义自己的shiro.ini文件

[main]
#身份认证没有成功跳转这个URL
authc.loginUrl = /login
#角色认证未通过
roles.unauthorizedUrl=/unauthorized.jsp
#权限认证未通过
perms.unauthorizedUrl=/unauthorized.jsp
[users]
liy313=123456,admin
jack=123,teacher
mary=123
[roles]
admin=user:*
teacher=student:*
[urls]
#请求login不需要身份认证,不然进入死循环
/login=anon
#进入比较敏感的URL需要身份认证
/admin=authc
/student=roles[teacher]
/teacher=perms["user:create"]
当一个用户没有登录,如果要访问某些URL比如/admin,首先会跳转到/login这个URL,由于[ruls]中/login设置为anon,表示不需要进行身份认证。

当一个用户访问已经登录后,访问/admin这个URL就可以成功了。

当用户liy313登录成功后,访问/student时由于需要roles中teacher这个角色,而该用户并没有teacher角色,则就会调用[mian]中的roles.unauthorizedUrl=/unauthorized.jsp。访问/teacher则会成功,因为liy313有admin的角色,而admin角色有user:*的所有权限。


Url 匹配方式
? 匹配一个字符 /admin?可以匹配/admin1 /admin2但是不能匹配/admin12 /admin
*
匹配零个或者一个或者多个字符 /admin*可以匹配 /admin /admin1 /admin12但是不能匹配/admin/abc
**
匹配零个或者多个路径 /admin/**可以匹配/admin /admin/a /admin/a/b


4.servlet

创建两个servlet用户模拟

LoginServlet,模拟登录时访问的servlet

package com.liy.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
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.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;

public class LoginServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("login");
		
		req.getRequestDispatcher("login.jsp").forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub

		String userName = req.getParameter("userName");
		String password = req.getParameter("password");
		
		//由于web环境启动时已经帮我们实例化securityManager,并绑定到SecurityUtils中,直接获取subject
		Subject currentUser = SecurityUtils.getSubject();
		//创建令牌
		UsernamePasswordToken token = new UsernamePasswordToken(userName,password);
		try {
			currentUser.login(token);
			resp.sendRedirect("success.jsp");
		} catch (Exception e) {
			e.printStackTrace();
			req.setAttribute("errInfo", "用户名或密码错误");
			req.getRequestDispatcher("login.jsp").forward(req, resp);
		}
	}	
}

AdminServlet,用户没有登录时访问会跳转或是登录后访问的servlet

package com.liy.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
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.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;

public class AdminServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("admin login get");
		
		
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub

		System.out.println("admin login post");
		
	}

	
}

并在web.xml文件中配置这两个servlet

<servlet>
		<servlet-name>loginServlet</servlet-name>
		<servlet-class>com.liy.servlet.LoginServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>loginServlet</servlet-name>
		<url-pattern>/login</url-pattern>
	</servlet-mapping>
	
	
	<servlet>
		<servlet-name>adminServlet</servlet-name>
		<servlet-class>com.liy.servlet.AdminServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>adminServlet</servlet-name>
		<url-pattern>/admin</url-pattern>
	</servlet-mapping>


5.jsp页面

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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="login" method="post">
	用户名:<input type="text" name="userName"><br/>
	密码:<input type="password" name="password"><br/>
	<input type="submit" value="登录">
	${errInfo }
</form>
</body>
</html>

成功跳转页面success.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>欢迎<shiro:principal/></h1>
</body>
</html>

角色或权限认证未通过的页面unauthorized.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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
认证未通过
</body>
</html>

6模拟

一、直接访问/admin,结果会跳转到login.jsp页面
二、当使用liy313用户登录,会跳转到success.jsp页面,<shiro:principal/>标签会显示主体信息即用户名。可以访问admin,并会等控制台输出admin login get,当访问/teacher这个URL时,出现404页面,因为模拟中没有配备/teacher的servlet,但表面已经通过了权限认证。当访问/student这个URL时,会跳转到unauthorized.jsp,因为liy313没有这个角色。
三、使用jack登录,同理



猜你喜欢

转载自blog.csdn.net/a1034386099/article/details/53164113
今日推荐