springboot集成shiro权限管理简单实现

下面就为您讲解“SpringBoot集成Shiro权限管理简单实现”的详细攻略。

一、配置

1.1 引入依赖

在Maven或Gradle中引入Shiro和SpringBoot的相关依赖:

Maven:

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-web</artifactId>
  <version>1.7.1</version> <!-- 版本可根据实际情况进行调整 -->
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Gradle:

implementation 'org.apache.shiro:shiro-web:1.7.1' // 版本可根据实际情况进行调整
implementation 'org.springframework.boot:spring-boot-starter-web'

1.2 配置Shiro

在SpringBoot中使用Shiro,我们需要在配置类(通常是Application.java)中添加一个ShiroFilterFactoryBean和一个DefaultWebSecurityManager的Bean。

示例代码:

@Configuration
public class Application {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        //创建shiroFilterFactoryBean 实例
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        //设置登录页面地址
        shiroFilterFactoryBean.setLoginUrl("/login");
        //设置无权限路径
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
        // 拦截器.
        Map<String, String> map = new HashMap<String, String>();
        // 配置不会被拦截的链接 顺序判断
        //anon:所有url都可以匿名访问
        map.put("/login", "anon");
        map.put("/static/**", "anon");  //静态资源不拦截
        map.put("/**", "authc");  //其他链接必须认证后才能访问
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        return shiroFilterFactoryBean;
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        //创建securityManager实例
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //设置realm
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    /**
     * 自定义realm
     */
    @Bean
    public MyShiroRealm myShiroRealm() {
        //创建realm实例
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }
}

1.3 配置Realm

自定义的Realm需要继承org.apache.shiro.realm.AuthorizingRealm类,实现其中的protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)和protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)方法,完成授权和身份认证的逻辑。

示例代码:

public class MyShiroRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //授权逻辑
        //获取当前用户
        User user = (User) principals.getPrimaryPrincipal();
        //创建授权对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //向授权对象中添加角色和权限
        authorizationInfo.addRoles(user.getRoles());
        authorizationInfo.addStringPermissions(user.getPermissions());
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //身份认证逻辑
        //获取用户输入的账号和密码
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();
        String password = new String(usernamePasswordToken.getPassword());
        //根据用户名查找数据库中的用户对象
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UnknownAccountException(); //账号不存在
        }
        if (!password.equals(user.getPassword())) {
            throw new IncorrectCredentialsException(); //密码错误
        }
        //创建身份认证对象
        return new SimpleAuthenticationInfo(user, password, getName());
    }
}

二、使用

2.1 创建用户实体类

public class User implements Serializable {

    private Integer id;
    private String username;
    private String password;
    private List<String> roles;
    private List<String> permissions;

    //省略getter和setter方法
}

2.2 设计登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <h1>登录</h1>
    <form action="/login" method="post">
        <p>用户名: <input type="text" name="username"></p>
        <p>密码: <input type="password" name="password"></p>
        <p><input type="submit" value="登录"></p>
    </form>
</body>
</html>

2.3 创建根据用户名查询用户的服务接口和实现类

public interface UserService {
    User findByUsername(String username);
}

@Service
public class UserServiceImpl implements UserService {

    @Override
    public User findByUsername(String username) {
        //模拟从数据库中查询用户
        if ("admin".equals(username)) {
            User user = new User();
            user.setUsername("admin");
            user.setPassword("123456");
            user.setRoles(Arrays.asList("admin"));
            user.setPermissions(Arrays.asList("user:select", "user:update", "user:delete"));
            return user;
        } else {
            return null;
        }
    }
}

2.4 编写授权和鉴权代码

在Controller中编写授权和鉴权代码,实现对鉴权失败的情况进行处理。

@RestController
public class UserController {

    @RequestMapping("/user/select")
    public String selectUser() {
        return "查询用户成功";
    }

    @RequestMapping("/user/update")
    public String updateUser() {
        return "更新用户信息成功";
    }

    @RequestMapping("/user/delete")
    public String deleteUser() {
        return "删除用户成功";
    }

    @RequestMapping("/unauthorized")
    public String unauthorized() {
        return "没有权限访问此页面";
    }
}

2.5 测试

完成上述步骤后,运行程序并访问localhost:8080/login,输入admin/123456登录后,访问/user/select、/user/update、/user/delete,应该能正常访问,否则将会跳转到unauthorized页面。

三、总结

至此,我们已经完成了SpringBoot集成Shiro权限管理的简单实现。在使用过程中需要注意:

  • 在自定义的Realm中返回的SimpleAuthenticationInfo对象中,第一个参数必须是用户对象。
  • 自定义的Realm必须添加到SecurityManager中。
  • 可以通过编写自定义的Filter实现更多的权限控制。
  • 若需要对部分用户进行特殊处理,可以重新实现AuthorizingRealm的授权方法。
  • 完整示例代码请参考GitHub上的开源项目。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springboot集成shiro权限管理简单实现 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Flink自定义Sink端实现过程讲解

    好的。首先,讲解Flink自定义Sink端实现过程,我们需要先了解Flink中DataStream API中对于Sink的定义。 Flink中,DataStream API提供了一些内置的Sink操作,如print、writeAsText等。这些内置的Sink操作可以满足大部分常见的业务需求,但对于一些特殊的需求,我们可能需要自己实现一些自定义的Sink操作…

    Java 2023年5月20日
    00
  • Java在并发环境中SimpleDateFormat多种解决方案

    Java中的SimpleDateFormat类是一个非线程安全的日期格式化工具,在并发环境中使用它可能会导致线程安全问题和性能问题。因此,我们需要对其进行一些处理,以便在多线程环境中使用。 下面是Java在并发环境中SimpleDateFormat多种解决方案的完整攻略: 方案一:使用ThreadLocal ThreadLocal是一种可以在多线程环境中正确…

    Java 2023年6月1日
    00
  • 浅谈JAVA字符串匹配算法indexOf函数的实现方法

    浅谈JAVA字符串匹配算法indexOf函数的实现方法 介绍 indexOf 是 JAVA 提供的一个用于字符串匹配的函数,它的作用是在一个给定的字符串中寻找另一个子字符串第一次出现的位置。在 JAVA 中,由于字符串是不可变的,所以 indexOf 是该语言中一个十分常用的方法。 indexOf的实现方法 在 JAVA 中,String 类有一个 inde…

    Java 2023年5月19日
    00
  • Spring boot基于JPA访问MySQL数据库的实现

    让我来给你讲解一下如何使用Spring Boot基于JPA访问MySQL数据库的实现以及示例。整个攻略将分为以下几个步骤: 创建一个Spring Boot项目 添加依赖 配置application.properties 建立实体类 建立Repository 建立Service 建立Controller 运行项目 下面是各个步骤的详细讲解: 1. 创建一个Sp…

    Java 2023年5月20日
    00
  • C++递归算法处理岛屿问题详解

    C++递归算法处理岛屿问题详解 什么是岛屿问题? 岛屿问题是指在一个由字母 O 和 X 组成的二维矩阵中,连成一片的 O 组成的区域被称为一个岛屿。请编写一个 C++ 程序,计算出给定的矩阵中岛屿的数量。 解题思路 解题的基本思路是对每个位置进行深度优先搜索,将和当前位置连通的所有 O 都标记为已访问。如此定义岛屿的个数即为进行深度优先搜索的次数。 接下来让…

    Java 2023年5月19日
    00
  • 解决Springboot启动报错:类文件具有错误的版本61.0,应为 52.0

    针对SpringBoot启动报错“类文件具有错误的版本61.0,应为52.0”,按照以下步骤进行解决: 1.问题原因 这个问题通常是因为编译器和运行环境版本不一致。使用较高版本的编译器编译的类文件,在低版本的运行环境中无法运行,导致启动失败。 2.解决过程 2.1 确认编译器和运行环境版本 首先需要确认代码使用的编译器版本以及部署环境的JDK版本是否一致。可…

    Java 2023年5月19日
    00
  • JAVA实现长连接(含心跳检测Demo)

    下面是“JAVA实现长连接(含心跳检测Demo)”的完整攻略。 1.什么是长连接? 长连接是指在TCP/IP连接中,长时间保持连接状态的一种网络通信方式。通常情况下,在客户端与服务器建立连接之后,即使在没有数据交互的情况下也保持连接状态。 相对于短连接,长连接的优势在于可以减少建立连接的开销,降低网络的负载,提高服务器的负载能力。 2.如何实现长连接? 实现…

    Java 2023年5月19日
    00
  • spring boot整合mybatis+mybatis-plus的示例代码

    下面我给您讲解一下“spring boot整合mybatis+mybatis-plus的示例代码”的完整攻略。 步骤1 – 添加依赖 首先,我们需要在 pom.xml 中添加以下依赖: <!– Spring Boot Mybatis Starter –> <dependency> <groupId>org.mybati…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部