Shrio 安全框架

目录

前言

1.介绍

[2.整合 Shiro 到 Spring Boot](#2.整合 Shiro 到 Spring Boot)

[3.Shiro 相关配置](#3.Shiro 相关配置)

总结


前言

几乎所有涉及用户的系统都需要进行权限管理,权限管理涉及到一个系统的安全。Spring Boot 的安全框架整合方案中还有一个璀璨的明珠:Shrio。


1.介绍

Shiro是一款由Java 编写的安全框架,功能强大,入手容易。Shiro 提供了一套完的RABC模式的授权认证体系,可以对密码进行加密,并完成安全的会话管理。与SpringSecurity 相比显得功能较少,但是对于追求"小而美"的解决方案的开发者和项目来说Shiro使用起来更加得心应手。

  1. 用于身份验证以及登录,检查用户是否拥有相应的角色权限。
  2. 进行权限验证,验证某个已登录认证的用户是否拥有某个具体的角色权限; 常的如:检验某个用户是否有对某些资源包括页面的访问和操作权限等。
  3. 进行会话管理,每当用户登录就是一次会话,在没有退出账号登录之前,用户的所有信息都在会话中存储。
  4. 对数据加密,保护数据的安全性,如密码加密存储到数据库,不是明文存储,更加安全。
  5. 对Web 支持,非常方便地集成到 Web 环境中
  6. 支持多线程并发验证。

这里介绍 Shiro 的一些核心的概念,Shiro 主要由三部分组成:

  1. Subject: 主体,外部应用会和 Subject 进行交互。Subject 会记录当前的用户,用在这里就是 Subject (主体),比如通过浏览器进行请求的用户。而 Subject 要通过 SecurityManager 进行认证授权。在代码层面,Subject 是一个定义了一些授权方法的接口 。
  2. Security Manager: 即安全管理器,它是 Shiro 的核心,将对所有的 Subject 进行安全管理。从代码层面上来说,Security Manager 是一个多继承接口,继承了Authenticator、Authorizer、SessionManager 这三个接口。
  3. Realm:是 Shiro 和安全应用之间的连接器,类似于一个安全相关的 DAO,在进行认证和授权时,Shiro 会从 Realm 中获取想要的数据

2.整合 Shiro 到 Spring Boot

新建一个 SpringBoot 项目 ,在 pom.xml 中添加如下配置:

XML 复制代码
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.7.0</version>
        </dependency>

3.Shiro 相关配置

在 applcation.yml 中编写相关配置。

Crystal 复制代码
shiro:
  # 开启 Shrio 配置,默认为 true
  enabled: true
  web:
    #开启 Shrio Web 配置,默认为 true
    enabled: true
  #配置登录地址,默认为"login.jsp"
  loginUrl: /login
  #配置登录成功地址 默认为 /
  successUrl: /index
  # 配置未获取授权默认跳转地址
  unauthorizedUrl: /unauthorized
  sessionManager:
  # 是否允许通过 Cookie,实现会话跟踪,默认为 true。
    sessionIdCookieEnabled: true
  #是否允许通过 URL 参数实现会话跟踪,默认为 true,如果网站支持 Cookie,可以关闭此选项
# thymeleaf
spring:
  thymeleaf:
   prefix: classpath:templates/
   suffix: .html
   mode: HTML
   encoding: UTF-8
   cache: false # 对于开发,最好禁用缓存

编写 ShiroConfig 文件,具体代码如下:

java 复制代码
package org.example.config;

import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.realm.text.TextConfigurationRealm;
@Configuration
public class ShiroConfig {

    @Bean
    public Realm realm(){
        TextConfigurationRealm realm = new TextConfigurationRealm();
        realm.setUserDefinitions("freephp=123456,user\n admin=123456,admin");
        realm.setRoleDefinitions("user=read\n admin=read,write");
        return  realm;
    }
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/logout","logout");
        chainDefinition.addPathDefinition("/login","anon");//匿名访问
        chainDefinition.addPathDefinition("/doLogin","anon");//匿名访问
        chainDefinition.addPathDefinition("/**","authc");
        return chainDefinition;
    }
}

上面的代码中有两个方法,一个是 realm 方法,另一个是 shiroFilterChainDefinition 方法。realm 方法用于获取权限认证数据,例如此处存储了两个账号:freephp 和 admin。

然后再编写 Controller 文件,只做简单的逻辑判断,代码如下:

java 复制代码
package org.example.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
    @RequestMapping("/doLogin")
    public String doLogin(String username, String password, Model model){
        System.out.println("userName is"+username);
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            return "index";
        }catch (AuthenticationException e){
            System.out.println(e.getCause());
            model.addAttribute("error","Username or Password is wrong!");
            return "login";
        }
    }
    @GetMapping("/admin")
    public String admin(){
        return "admin";
    }

    @GetMapping("/user")
    public String user(){
        return "user";
    }

}

上面的代码定义了三个接口,其中 doLogin 用于登录,使用 UsernamePasswordToken 类创建 token。然后根据账号和密码进行匹配判断,如果验证失败则返回 /dologin 页面并显示错误提示,如果验证成功则可以访问 index 页面。

登录页面和首页页面都需要单独编写,在 resources 目录下创建 templates 文件夹,然后分别创建 index.html 和 login.html。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
hi,test
</body>
</html>
html 复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
<form action="/doLogin" method="post">
    <label>username:</label>
    <input type="text" name="username"><br/>
    <label>password:</label>
    <input type="text" name="password"><br/>
    <div th:text>${error}</div>
    <input type="submit" value="登录"/>
 </form>
</body>
</html>

为了更好的加载上面的页面,编写一个 WebMvcConfig 来加载:

java 复制代码
package org.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("index").setViewName("index");
        registry.addViewController("login").setViewName("login");
    }
}

访问之后,输入正确的账号和密码,则可以看到登录成功的页面,反之则提示登录失败。


总结

Shiro 的使用非常方便,只需实现最核心的 realm 定义和 shiroFilterChainDefinition 功能就可以很好地完成认证授权功能。除此之外,Shiro 还提供缓存功能,感兴趣的同学可以自行查阅官方文档进行学习。

相关推荐
郑州吴彦祖7721 分钟前
【java】数据类型与变量以及操作符
java·intellij-idea
程序员大金3 分钟前
基于SpringBoot+Vue+MySQL的在线学习交流平台
java·vue.js·spring boot·后端·学习·mysql·intellij-idea
吹老师个人app编程教学8 分钟前
阿里巴巴_java开发规范手册详解
java·开发语言
天上掉下来个程小白8 分钟前
Stream流的终结方法(一)
java·windows
qq_25183645710 分钟前
基于SpringBoot vue 医院病房信息管理系统设计与实现
vue.js·spring boot·后端
创小董18 分钟前
低空经济时代:无人机飞行安全要点详解
安全·无人机
天上掉下来个程小白30 分钟前
请求响应-08.响应-案例
java·服务器·前端·springboot
大白_dev30 分钟前
数据校验的总结
java·开发语言
武昌库里写JAVA31 分钟前
Vue3常用API总结
数据结构·spring boot·算法·bootstrap·课程设计
失落的香蕉37 分钟前
Java第二阶段---10方法带参---第三节 面向对象和面向过程的区别
java·开发语言