Shiro權限管理框架(Java安全框架)基礎

一、Shiro 簡介

1、關於 Shiro

  • Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼和會話管理。使用Shiro的易於理解的API,您可以快速、輕鬆地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。
  • 官網:https://shiro.apache.org/

2、Shiro 主要功能

在這裏插入圖片描述

  • Authentication:身份認證/登錄,驗證用戶是不是擁有相應的身份;
  • Authorization:授權,即權限驗證,驗證某個已認證的用戶是否擁有某個權限;即判斷用戶是否能做事情,常見的如:驗證某個用戶是否擁有某個角色。或者細粒度的驗證某個用戶對某個資源是否具有某個權限;
  • Session Manager:會話管理,即用戶登錄後就是一次會話,在沒有退出之前,它的所有信息都在會話中;會話可以是普通 JavaSE 環境的,也可以是如 Web 環境的;
  • Cryptography:加密,保護數據的安全性,如密碼加密存儲到數據庫,而不是明文存儲;
  • Web Support:Web 支持,可以非常容易的集成到 Web 環境;
  • Caching:緩存,比如用戶登錄後,其用戶信息、擁有的角色/權限不必每次去查,這樣Remember Me:記住我,這個是非常常見的功能,即一次登錄後,下次再來的話不用登錄

3、Shiro 的工作原理

在這裏插入圖片描述

  • Subject:主體,代表了當前“用戶”,這個用戶不一定是一個具體的人,與當前應用交互的任何東西都是 Subject,如網絡爬蟲,機器人等;即一個抽象概念;所有 Subject 都綁定到 SecurityManager,與 Subject 的所有交互都會委託給 SecurityManager;可以把 Subject 認爲是一個門面;SecurityManager 纔是實際的執行者;

  • SecurityManager:安全管理器;即所有與安全有關的操作都會與 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它負責與後邊介紹的其他組件進行交互,如果學習過 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;

  • Realm:域 Shiro 從 Realm 獲取安全數據(如用戶、 角色、 權限) ,就是說 SecurityManager要驗證用戶身份, 那麼它需要從 Realm 獲取相應的用戶進行比較以確定用戶身份是否合法; 也需要從 Realm 得到用戶相應的角色/權限進行驗證用戶是否能進行操作; 可以把 Realm 看成 DataSource,即安全數據,可以理解成Dao組件訪問權限數據的組件

二、Shiro 入門案例(整合web項目)

第一步:pom.xml 引入maven包
  • shiro-core
  • shiro-web
  • commons-logging(日誌記錄)
  • mysql-connector-java
  • druid
  • javax.servlet-api
第二步:web.xml配置(在main/java/webapp/WEB-INF/web.xml)
<?xml version="1.0" encoding="UTF-8"?>
<web-app
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        version="3.0"
        metadata-complete="false">

    <!--- shiro 1.2 -->
    <!-- 加載shiro配置文件 -->
    <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><!-- 默認先從/WEB-INF/shiro.ini,如果沒有找classpath:shiro.ini -->
    </context-param>
    <context-param>
        <param-name>shiroConfigLocations</param-name>
        <param-value>classpath:shiro-formfilter.ini</param-value>
    </context-param>
    
    <!-- 配置shiro的過濾器 -->
    <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]
authc.loginUrl=/login.jsp
roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=/unauthorized.jsp

[users]
zhang=123,admin
wang=123

[roles]
admin=user:*,menu:*

[urls]
/login=anon
/logout2=logout
/role.jsp=roles[admin]
/permission.jsp=perms[user:create]
/**=user

在上面的代碼中:
在這裏插入圖片描述

第四步:登錄 LoginServlet.java
package cn.lemon.shiro.web.servlet;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
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 java.io.IOException;

@WebServlet(name = "loginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String error = null;
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(true);
        try {
            subject.login(token);/*根據用戶名密碼令牌,判斷和shiro.ini中的zhangsan=123,wang=123是否匹配*/
        } catch (UnknownAccountException e) {
            error = "用戶名錯誤";
        } catch (IncorrectCredentialsException e) {
            error = "密碼錯誤";
        } catch (AuthenticationException e) {
            //其他錯誤,比如鎖定,如果想單獨處理請單獨catch處理
            error = "其他錯誤:" + e.getMessage();
        }

        if(error != null) {//出錯了,返回登錄頁面
            req.setAttribute("error", error);
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        } else {//登錄成功
        	req.getSession().setAttribute("subject", subject);
            req.getRequestDispatcher("/index.jsp").forward(req, resp);
        }
    }
}
第五步:login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登錄</title>
    <style>.error{color:red;}</style>
</head>
<body>
<h5>login.jsp</h5>
<div class="error">${error}</div>
<form action="${pageContext.request.contextPath}/login" method="post">
    用戶名:<input type="text" name="username"><br/>
    密碼:<input type="password" name="password"><br/>
    <input type="submit" value="登錄">
</form>
</body>
</html>
第六步:註銷 LogoutServlet.java
package cn.lemon.shiro.web.servlet;

import org.apache.shiro.SecurityUtils;
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 java.io.IOException;

@WebServlet(name = "logoutServlet", urlPatterns = "/logout")
public class LogoutServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        SecurityUtils.getSubject().logout();
        req.getRequestDispatcher("/login.jsp").forward(req, resp);
    }
}
第七步:shiro-formfilter.ini
[main]
authc.loginUrl=/formfilterlogin
roles.loginUrl=/formfilterlogin
perms.loginUrl=/formfilterlogin

roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=/unauthorized.jsp

[users]
zhang=123,admin
wang=123

[roles]
admin=user:*,menu:*

[urls]
/formfilterlogin=authc

/login=anon
/logout2=logout
/role.jsp=roles[admin]
/permission.jsp=perms[user:create]
/**=authc
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章