Shiro权限管理框架(Java安全框架)基础

一、Shiro 简介

1、关于 Shiro

  • Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
  • 官网:https://shiro.apache.org/

2、Shiro 主要功能

Shiro权限管理框架(Java安全框架)基础_第1张图片

  • Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
  • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
  • Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
  • Web Support:Web 支持,可以非常容易的集成到 Web 环境;
  • Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录

3、Shiro 的工作原理

Shiro权限管理框架(Java安全框架)基础_第2张图片

  • 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)

<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">

    
    
    <listener>
        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListenerlistener-class>
    listener>
    <context-param>
        <param-name>shiroEnvironmentClassparam-name>
        <param-value>org.apache.shiro.web.env.IniWebEnvironmentparam-value>
    context-param>
    <context-param>
        <param-name>shiroConfigLocationsparam-name>
        <param-value>classpath:shiro-formfilter.iniparam-value>
    context-param>
    
    
    <filter>
        <filter-name>shiroFilterfilter-name>
        <filter-class>org.apache.shiro.web.servlet.ShiroFilterfilter-class>
    filter>
    <filter-mapping>
        <filter-name>shiroFilterfilter-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

在上面的代码中:
Shiro权限管理框架(Java安全框架)基础_第3张图片

第四步:登录 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.jsph5>
<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

你可能感兴趣的:(Shiro)