SpringBoot——安全管理(五)

一、Shiro简介

Apache Shiro是一个相对开源的轻量级的Java安全框架,它提供身份验证、授权、密码管理以及会话管理等功能。相对于Spring Security,Shiro框架更加直观、易用,同时也能提供健壮的安全性。在传统的SSM框架中,手动整合Shiro的配置步骤还是比较多的,针对SpringBoot,Shiro官方提供了**shiro-spring-boot-web-starter**用来简化Shiro在SpringBoot中的配置

二、整合Shrio

  1. 创建项目
    首先创建一个普通的Spring Boot Web项目,添加Shiro依赖以及页面模板依赖,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.3</version>
        <relativePath/>
    </parent>
    <groupId>com.shrio</groupId>
    <artifactId>shirotest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
    </dependencies>
</project>

注意这里不需要添加spring-boot-starter-web依赖,shiro-spring-boot-web-starter中已经依赖了spring-boot-starter-web。同时,使用Thymeleaf依赖,因此添加Thymeleaf依赖,另外,为了在Thymeleaf中使用shiro标签,因此引入了thymeleaf-extras-shiro依赖

  1. Shiro基本配置
  • 首先在application.properties中配置Shiro的基本信息。
#表示开启Shiro配置,默认为true
shiro.enabled=true
#表示开启Shiro Web配置,默认为true
shiro.web.enabled=true
#表示登录地址 默认为/login.jsp
shiro.loginUrl=/login
#表示登录成功地址 默认为"/"
shiro.successUrl=/index
#表示未获授权默认跳转地址
shiro.unauthorizedUrl=/unauthorized
#表示是否允许通过URL参数实现会话跟踪,如果网站支持Cookie,可以关闭
#此选项
shiro.sessionManager.sessionIdUrlRewritingEnabled=true
#表示是否允许通过Cookie实现会话跟踪,默认为true
shiro.sessionManager.sessionIdCookieEnabled=true
  • 配置Shiro,提供两个最基础的Bean即可
/**
 * 提供两个关键Bean,一个是Realm,另一个是ShiroFilterChainDefinition
 * 至于ShiroDialect则是为了支持在Thymeleaf中使用Shiro标签
 * 如果不在Thymeleaf中使用Shiro标签,那么可以不提供ShiroDialect
 */
@Configuration
public class ShiroConfig {

    /**
     * Realm 可以自定义Realm,也可以是Shiro提供的Realm
     * 简单起见,没有配置数据库连接,这里直接配置了两个用户:
     * sang/123和admin/123,分别对应角色user和admin
     * user具有read权限,admin则具有read、write权限
     * @return
     */
    @Bean
    public Realm realm() {
        TextConfigurationRealm realm = new TextConfigurationRealm();
        realm.setUserDefinitions("sang=123,user\n admin=123,admin");
        realm.setRoleDefinitions("admin=read,write\n user=read");
        return realm;
    }

    /**
     * ShiroFilterChainDefinition Bean中配置了基本的过滤规则
     * @return
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/login", "anon");//可以匿名访问
        chainDefinition.addPathDefinition("/doLogin", "anon");//可以匿名访问
        chainDefinition.addPathDefinition("/logout", "logout");//注销登录请求
        chainDefinition.addPathDefinition("/**", "authc");//其余请求则都需要认证后才能访问
        return chainDefinition;
    }

    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
}
  • 配置登录接口以及页面访问接口
@Controller
public class UserController {

    /**
     * 创建一个UsernamePasswordToken实例,然后获取一个Subject对象
     * 并调用该对象中的login方法执行登录操作,在登录操作执行过程中,当有异常
     * 抛出时,说明登录失败,携带错误信息返回登录视图;当登录成功时,则重定向到”/index“
     * @param username
     * @param password
     * @param model
     * @return
     */
    @PostMapping("/doLogin")
    public String doLogin(String username, String password, Model model) {
        UsernamePasswordToken token =
                new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            model.addAttribute("error", "用户名或密码输入错误!");
            return "login";
        }
        return "redirect:/index";
    }

    /**
     * 需要admin权限才能访问
     * @return
     */
    @RequiresRoles("admin")
    @GetMapping("/admin")
    public String admin() {
        return "admin";
    }

    /**
     * 需要admin和user权限中的任意一个即可访问
     * @return
     */
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @GetMapping("/user")
    public String user() {
        return "user";
    }
}
  • 对于其他不需要角色就能访问的接口,直接在WebMvc中配置即可
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/index").setViewName("index");
        registry.addViewController("/unauthorized").setViewName("unauthorized");
    }
}

  • 创建全局异常处理器进行全局异常处理
@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(UnauthorizedException.class)
    public ModelAndView error(UnauthorizedException e) {
        ModelAndView mv = new ModelAndView("unauthorized");
        mv.addObject("error", e.getMessage());
        return mv;
    }
}

当用户访问未授权的资源时,跳转到unauthorized视图中,携带错误信息。
配置完成后,最后在resources/templates目录下创建5 个HTML页面进行测试

  1. index.html
<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>Hello, <shiro:principal/></h3>
<h3><a href="/logout">注销登录</a> </h3>
<h3><a shiro:hasRole="admin" href="/amdin">管理员页面</a> </h3>
<h3><a shiro:hasAnyRoles="admin,user" href="/user">普通用户页面</a> </h3>
</body>
</html>

  1. admin.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
   <h1>管理员页面</h1>
</div>
</body>
</html>

  1. login.html
<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <form action="/doLogin" method="post">
        <input type="text" name="username"/><br/>
        <input type="password" name="password"><br/>
        <div th:test="${error}">
            <input type="submit" value="登录"/>
        </div>
    </form>
</div>
</body>
</html>

  1. unauthorized.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <h3>未获授权,非法访问</h3>
    <h3 th:text="${error}"></h3>
</div>
</body>
</html>

  1. user.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>普通用户页面</h1>
</body>
</html>

三、测试

配置完成后,启动项目,访问登录页面,分别使用sang/123和admin/123登录,如下图所示

  • sang登录
    在这里插入图片描述
  • admin登录
    在这里插入图片描述
    登录成功后,无论是sang还是admin用户,单击"注销登录"都会注销成功,然后回到登录页面,sang用户因为不具备admin角色,因此没有”管理员页面“的超链接,无法进入管理员页面中,此时,若用户使用sang用户登录,然后手动在地址栏输入http://localhost:8080/amdin,则会跳转到未授权页面
    在这里插入图片描述
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值