Shiro--集成SpringBoot(一)

创建项目,引入依赖

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

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

Shiro基本配置

在appliaction.properties中配置Shiro的基本信息:

# 开启Shiro配置,默认为true
shiro.enabled=true

# 开启Shiro Web配置,默认为true
shiro.web.enabled=true

# 登录地址
shiro.loginUrl=/login

# 登录成功的地址,默认为"/"
shiro.successUrl=/index

# 未授权的默认跳转地址
shiro.unauthorizedUrl=/unauthorized

# 是否允许通过URL参数实现会挂跟踪,默认为true
shiro.sessionManager.sessionIdCookieEnabled=true

# 是否允许通过Cookie实现会话跟踪,默认为true
shiro.sessionManager.sessionIdUrlRewritingEnabled=true

配置类:

package pers.zhang.demo.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.TextConfigurationRealm;
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;

/**
 * @Author: acton_zhang
 * @Date: 2020/2/10 9:22 下午
 * @Version 1.0
 */
@Configuration
public class ShiroConfig {

    @Bean
    public Realm realm(){
        TextConfigurationRealm realm = new TextConfigurationRealm();
        //配置两个用户:sang/123 角色为user;  admin/123 角色为admin
        realm.setUserDefinitions("sang=123,user\n admin=123,admin");
        //user具有read权限;        admin具有read和write权限;
        realm.setRoleDefinitions("admin=read,write\n user=read");
        return realm;
    }


    //定义基本过滤规则
    /*
        "/login"和"/doLogin"可以匿名访问
        "/logout"是注销登录请求
        其余请求都需要认证后访问
     */
    @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;
    }


    //为了支持在Thymeleaf中使用Shiro标签
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }
}

Controller

配置登录接口以及页面访问接口:

package pers.zhang.demo.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
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.PostMapping;

/**
 * @Author: acton_zhang
 * @Date: 2020/2/10 9:32 下午
 * @Version 1.0
 */
@Controller
public class UserController {

    @PostMapping("/doLogin")
    public String doLogin(String username, String password, Model model){
        //构建一个UsernamePasswordToken实例
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        //获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        try{
            //认证
            subject.login(token);
        }catch (AuthenticationException e){
            model.addAttribute("error", "用户名或密码输入错误!");
            return "login";
        }
        return "redirect:index";

    }

    //具有admin角色才可以访问"/admin"接口
    @RequiresRoles("admin")
    @GetMapping("/admin")
    public String admin(){
        return "admin";
    }

    //具有admin或user角色任意一个即可访问"/user"接口
    @RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
    @GetMapping("/user")
    public String user(){
        return "user";
    }
}

对于其它不要角色就能访问的接口,直接在WebMvc中配制即可:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    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(AuthorizationException.class)
    public ModelAndView error(AuthorizationException e){
        ModelAndView mv = new ModelAndView("unauthorized");
        mv.addObject("error", e.getMessage());
        return mv;
    }
}

页面

在resources/templates目录下创建5个HTML。

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="/admin">管理员页面</a> </h3>
    <h3><a shiro:hasAnyRoles="admin,user" href="/user">普通用户页面</a> </h3>
</body>
</html>

login.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<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:text="${error}"></div>
            <input type="submit" value="登录"/>
        </form>
    </div>
</body>
</html>

user.html:

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

admin.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>管理员页面</h1>
</body>
</html>

unauthorized.html:

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

测试

使用sang/123访问:

因为sang用户不具备admin角色,因此登录成功后的页面上没有前往管理员页面的超链接。
在这里插入图片描述
在这里插入图片描述

使用admin/123访问:

admin具有admin角色和user角色,所以登录成功后会显示『管理员页面』和『普通用户页面』:
在这里插入图片描述
在这里插入图片描述

使用sang/123登录后,直接访问"/admin"接口:

因为sang不具备admin角色,所以会跳转到错误页面:
在这里插入图片描述

发布了750 篇原创文章 · 获赞 2115 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/cold___play/article/details/104256124