Shrio 安全框架

2023-12-14 21:30:13

目录

前言

1.介绍

2.整合 Shiro 到 Spring Boot

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 中添加如下配置:

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.7.0</version>
        </dependency>

3.Shiro 相关配置

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

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 文件,具体代码如下:

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 文件,只做简单的逻辑判断,代码如下:

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。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
hi,test
</body>
</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 来加载:

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 还提供缓存功能,感兴趣的同学可以自行查阅官方文档进行学习。

文章来源:https://blog.csdn.net/m0_62943934/article/details/134884974
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。