0
点赞
收藏
分享

微信扫一扫

SpringBoot整合Shiro

无愠色 2023-07-13 阅读 67

Shiro是什么?是 Java 的一个安全框架,主要功能是实现认证与授权

步骤:

1.添加依赖

2.自定义Realm类执行授权和认证的逻辑

3.创建Shiro的配置类

4.创建登录的页面,成功的页面,提示无权限的页面

5.编写LoginController

6.运行测试

具体步骤如下:

- 1.依赖

-  <!--thymeleaf依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--shiro依赖,实现认证与授权-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>


- 2.自定义 Realm 类,

执行授权和认证的逻辑, Realm 充当了 Shiro 与应用安全数据之间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro 会从应用配置的 Realm 中查找用户及其权限信息

   

package com.xxx.common.shiro;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class UserRealm extends AuthorizingRealm {
    /**
     * 执行授权逻辑
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        System.out.println("执行授权逻辑");
        return null;
    }

    /**
     * 执行认证逻辑
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
        System.out.println("执行认证逻辑");

        //假设数据库的用户名和密码
        String name = "admin";
        String password = "123456";
        //编写shiro判断逻辑,判断用户名和密码
        //1.判断用户名
        UsernamePasswordToken token = (UsernamePasswordToken) arg0;
        if (!token.getUsername().equals(name)) {
            //用户名不存在
            return null;//shiro底层会抛出UnKnowAccountException
        }
        //2.判断密码
        return new SimpleAuthenticationInfo("", password, "");
    }
}


3.创建Shiro配置类

  SecurityManager 会去 Authenticator(认证器)中查找相应的Realms,Realms 可以根据不同类型的 Realm 去查找用户信息,并进行判断是否认证成功。当配置 Shiro 时,你必须至少指定一个Realm,用于认证和(或)授权。也可以配置多个 Realm,但至少需要一个.

package com.xxx.common.shiro;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Shiro的配置类
 */
@Configuration
public class ShiroConfig {

    /**
     * 创建ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /**
         * Shiro内置过滤器,可以实现权限相关的拦截器
         * 常用的过滤器:
         * anon: 无需认证(登录)可以访问
         * authc: 必须认证才可以访问
         * user: 如果使用rememberMe的功能可以直接访问
         * perms: 该资源必须得到资源权限才可以访问
         * role: 该资源必须得到角色权限才可以访问
         *
         * URL 匹配及过滤规则汇总如下:
         * 1) ”?”:匹配一个字符,如”/admin?”,将匹配” /admin1”、”/admin2”,但不匹配”/admin”;
         * 2) ”*”:匹配零个或多个字符串,如”/admin*”,将匹配” /admin”、”/admin123”,但不匹配”/admin/1”;
         * 3) ”**”:匹配路径中的零个或多个路径,如”/admin/**”,将匹配”/admin/a”、”/admin/a/b”;
         * 4) anon:匿名过滤器,表示通过了 url 配置的资源都可以访问,如:“/statics/**=anon”表示statics目录下所有资源都能访问;
         * 5) authc:基于表单的过滤器,表示通过了 url 配置的资源需要登录验证,否则跳转到登录,如:“/unauthor.jsp=authc”如果用户没有登录访问 unauthor.jsp 则直接跳转到登录。
         */
        Map<String,String> filterMap = new LinkedHashMap<String,String>();
        filterMap.put("/testThymeleaf", "anon");
        filterMap.put("/login", "anon");
        filterMap.put("/**", "authc");
        //修改调整的登录页面
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 创建DefaultWebSecurityManager
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
         DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    /**
     * 创建Realm
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm() {
        return new UserRealm();
    }
}


- 4.创建登录页面、成功页面和无权限提示页面

在 templates 目录下新建页面 login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面:测试shiro</title>
</head>
<body>
<h3>登录</h3>
<form method="post" action="login">
    用户名:<input type="text" name="name"/><br/>
    密码:<input type="password" name="password"/><br/>
    <input type="submit" value="登录"/>
</form>
</body>
</html>


  在templates目录下创建test.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Thymeleaf的使用</title>
</head>
<body>
<h3 th:text="${name}"></h3>
</body>
</html>


   在templates目录下创建noAuth.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>没有权限</h1>
</body>
</html>


- 编写LoginController

package com.xxx.controller;

import org.apache.shiro.SecurityUtils;
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 org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class LoginController {

    /**
     * 登录逻辑处理
     */
    @RequestMapping("/login")
    public String login(String name, String password, Model model) {
        /**
         * 使用Shiro编写认证操作
         */
        // 1.获取Subject
        Subject subject = SecurityUtils.getSubject();
        // 2.封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(name, password);
        // 3.执行登录方法
        try {
            subject.login(token);
            // 登录成功
            // 跳转到test.html
            return "redirect:/testThymeleaf";
        } catch (UnknownAccountException e) {
            // 登录失败:用户名不存在
            model.addAttribute("msg", "用户名不存在");
            return "login";
        } catch (IncorrectCredentialsException e) {
            // 登录失败:密码错误
            model.addAttribute("msg", "密码错误");
            return "login";
        }
    }

    @RequestMapping("/toLogin")
    public String toLogin(Model model) {
        return "login";
    }

    @RequestMapping("/toNoAuth")
    public String toNoAuth(Model model) {
        return "noAuth";
    }


    /**
     * 测试Thymeleaf:
     * 将带着数据跳转到模板文件夹下的test.html文件中显示
     *
     * @param model
     * @return
     */
    @RequestMapping("/testThymeleaf")
    public String testThymeleaf(Model model) {
        //把数据存入model
        model.addAttribute("name", "Hello");
        //返回test.html
        return "test";
    }


}

- 运行测试

在shiro配置类中已经设置了需认证的请求及拦截跳转登录页,所以启动项目后,地址随便拼写都是自动跳转到登录页,(包括静态),登录成功后,即可访问其他资源,关闭浏览器即失效

[{"src":"xap:resources/18e040240c3f0df0cfd2cf05c8bfdf294d1849e98d29681d2ac5358671749429.png","width":495,"height":324}]

 请求地址为index.html,程序会自动跳转到登录

- shiro实现授权:

    - 有些资源没有权限就访问不到

    - 修改配置类:

        - 设置哪些资源需要什么权限

filterMap.put("/getUserList", "perms[user:get]");

        - 如果没有权限怎么办? 跳转到无权限的页面

shiroFilterFactoryBean.setUnauthorizedUrl("/toNoAuth");


    - 在controller中有处理toNoAuth请求的代码,跳转到对应的页面

@RequestMapping("/toNoAuth")
    public String toNoAuth(Model model) {
        return "noAuth";
    }


    - 运行测试,登录成功后,getUserList资源还是访问不了,会验证是否拥有user:get的权限(字符串),会跳转到对应的提示页面

    - 修改自定义Realm类,设置对应的权限


     

-  /**
     * 执行授权逻辑
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        System.out.println("执行授权逻辑");
//        return null;
        // 给资源进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 添加资源的授权字符串
        info.addStringPermission("user:get");
        return info;
    }


    - 运行测试,再次登录成功后,getUserList资源可以访问了



举报

相关推荐

0 条评论