第五章:Shiro集成Web开发(重点:用户、角色、权限认证)
这一章主要内容:
1. shiro集成web中开发
2. 通过shiro.ini配置静态用户/角色/权限信息【暂时没有到db中取数】
3. 进行用户/角色/权限的认证
----------------------------------------------
工程结构:
用户登录认证:
一、创建web类型的maven工程【创建的工程不是web的,要修改工程结构,
请参照这里修改:http://www.cnblogs.com/josephcnblog/articles/6816564.html】
二、改好工程结构之后,修改pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.java1234.shiro</groupId>
<artifactId>ShiroWeb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- 这里还要添加shiro的核心包和shiro的web支持, 如果不能引入就直接引入jar包 -->
<!-- 添加Junit支持 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
</dependency>
<!-- 添加Servlet支持 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- 添加JSP支持 -->
<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>
<!-- 添加日志支持 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
</dependencies>
</project>
三、在WEB-INF下创建shiro.ini,配置好用户/角色/权限,固定写法,
[main] 配置对象及其属性, 例如:SecurityManager, Realms;
[users] 配置用户信息/角色信息, 只是配置一小部分用户信息, 实际开发中这种配置并不合适;
[roles] 配置角色的操作权限, 实际开发中也不会在这里配置,要存储到数据库;
[urls] 配置页面跳转信息, 权限跳转 。
具体看:
[main] authc.loginUrl = /login [users] java1234 = 123456, admin jack = 123, teacher marry = 234 json = 345 [roles] admin = user:* teacher = student:* [urls] /login = anon /admin = authc
四、在webapp下创建login.jsp
<form action="login" method="post">
userName: <input type="text" name="userName"/><br>
password: <input type="text" name="password"/><br>
<input type="submit" value="登录"/>
</form>
五、包com.java1234.servlet下创建
LoginServlet.java
package com.java1234.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 { System.out.println("Login doGet()..."); req.getRequestDispatcher("login.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Login doPost()..."); // 接收登录的用户名和密码 String userName = req.getParameter("userName"); String password = req.getParameter("password"); // 将登录的用户名和密码绑定到令牌Token UsernamePasswordToken token = new UsernamePasswordToken(userName, password); // 获取登录对象 Subject subject = SecurityUtils.getSubject(); // 尝试登录 try { subject.login(token); // 登录校验 resp.sendRedirect("success.jsp"); // 登录成功 } catch (Exception e) { // 登录失败 e.printStackTrace(); req.setAttribute("errorInfo", "用户名或密码错误!"); req.getRequestDispatcher("login.jsp").forward(req, resp); } } }
AdminServlet.java【用于测试登录用】
package com.java1234.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AdminServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Admin doGet()..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Admin doPost()..."); } }
六、在WEB-INF下创建web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ShiroWeb</display-name> <welcome-file-list> <welcome-file>login.jsp</welcome-file> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 配置shiro监听 --> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <!-- 配置shiro过滤器: 每一次请求都要经过shiro过滤 --> <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> <init-param> <param-name>configPath</param-name> <param-value>/WEB-INF/shiro.ini</param-value> </init-param> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置servlet --> <servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.java1234.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.java1234.servlet.AdminServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AdminServlet</servlet-name> <url-pattern>/admin</url-pattern> </servlet-mapping> </web-app>
七、在webapp下创建success.jsp
<h1>欢迎您!</h1>
测试
(1)输入错误的用户名/密码,登录后跳转到登录页面 ; 或者直接在地址栏输入/admin,也会被拦截到登录界面
后台打印:Login doPost()...,并且报错:没有匹配的用户
(2)输入正确的用户名/密码,跳转到了success.jsp页面,
这时候再输入/admin, 就不报错, 后台打印:Admin doGet()...
--------------------------------------------------
角色认证
在shiro.ini的[main]下添加角色拦截
roles.unauthorizedUrl=/unauthorized.jsp
在shiro.ini的[urls]下添加角色拦截
/student=roles[teacher]
以上配置表示在访问/student的时候,如果没有teacher这个角色,那么将被拦截到unauthorized.jsp
根据shiro.ini,可知,用户jack=123这个用户有teacher这个角色,其他用户访问/student都将被拦截到unauthorized.jsp
测试:前提是先要进行用户登录认证,然后才能进行角色认证,否则直接报错!
(1)使用jack/123用户测试
-->
-->
, 报错是因为没有写student的Servlet,报错是正确的!
(2)使用marry=234用户测试
-->
-->
权限认证
在shiro.ini中添加角色拦截:
[main]下添加 perms.unauthorizedUrl=/unauthorized.jsp
[urls]下添加 /teacher=perms["user:create"] 表示有"user:create"这个权限的用户才能访问/teacher,
否则将被perms.unauthorizedUrl=/unauthorized.jsp拦截到unauthorized.jsp页面
测试:
(1)用java1234=123456登录
因为这个用户有admin角色,而且admin角色有user:*的权限,所以java1234=123456这个用户有"user:create"这个权限
因为没有写teacher的servlet,所以报错是正确的!
(2)用jack=123, teacher登录
因为这个用户有teacher角色,但是teacher这个角色没有user:create权限,只有student:*的权限,所以将被拦截