当前位置: 技术文章>> Shiro的与Hibernate集成

文章标题:Shiro的与Hibernate集成
  • 文章分类: 后端
  • 6930 阅读
文章标签: java java高级

Shiro与Hibernate集成指南

在Java企业级应用中,权限管理和数据持久化是两个至关重要的方面。Apache Shiro作为一个功能强大的安全框架,提供了认证、授权、加密和会话管理等核心功能,而Hibernate则是Java领域中广泛使用的对象关系映射(ORM)框架,能够简化数据库操作。将Shiro与Hibernate集成,可以在确保应用安全的同时,高效地进行数据管理。本文将详细介绍如何在一个Java项目中实现Shiro与Hibernate的集成,并通过实际代码示例进行说明。

一、项目环境搭建

首先,我们需要搭建一个基本的Java Web项目环境,并引入必要的依赖。假设我们使用的是Maven作为项目管理工具,项目的pom.xml文件中需要包含Shiro和Hibernate的相关依赖。

Maven依赖配置
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>5.3.10</spring.version>
    <hibernate.version>5.4.32.Final</hibernate.version>
    <shiro.version>1.7.1</shiro.version>
</properties>

<dependencies>
    <!-- Spring Framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- Shiro -->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>${shiro.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>${shiro.version}</version>
    </dependency>
    <!-- Hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <!-- Hibernate Validator -->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.1.7.Final</version>
    </dependency>
    <!-- 数据库连接池 -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
        <version>1.4.200</version>
    </dependency>
    <!-- 其他依赖... -->
</dependencies>

这里我们使用了H2数据库作为示例,因为它是一个轻量级的嵌入式数据库,适合开发和测试环境。在生产环境中,你可能需要替换为MySQL、Oracle等数据库,并相应地调整JDBC连接字符串和驱动依赖。

二、数据库设计与实体映射

在Shiro与Hibernate集成中,数据库设计是关键一环。通常,我们需要设计用户表、角色表、权限表以及它们之间的关联表。

数据库表结构
  1. t_user(用户表)

    • user_id (主键)
    • username (用户名)
    • password (密码,加密存储)
    • ...
  2. t_role(角色表)

    • role_id (主键)
    • role_name (角色名)
    • ...
  3. t_permission(权限表)

    • permission_id (主键)
    • permission_name (权限名)
    • ...
  4. t_user_role(用户-角色关联表)

    • user_id (外键)
    • role_id (外键)
  5. t_role_permission(角色-权限关联表)

    • role_id (外键)
    • permission_id (外键)
实体类定义

对应上述数据库表,我们需要定义相应的实体类。这里仅展示UserRole的示例代码,其他实体类(如Permission)的定义类似。

@Entity
@Table(name = "t_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;
    
    @Column(unique = true, nullable = false)
    private String username;
    
    @Column(nullable = false)
    @JsonIgnore // 用于JSON序列化时忽略密码字段
    private String password;
    
    // 省略getter和setter方法
    
    // 用户与角色的关系,使用@ManyToMany注解表示多对多关系,但这里通过中间表实现,故不直接标注
    // 实际开发中,可能会使用@JoinTable注解进一步说明中间表的信息
}

@Entity
@Table(name = "t_role")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long roleId;
    
    @Column(nullable = false)
    private String roleName;
    
    // 省略getter和setter方法
    
    // 角色与权限的关系,同样通过中间表实现
}

注意,这里我们使用了JPA注解来定义实体与数据库表之间的映射关系。在实际项目中,你可能还需要根据业务需求添加更多的字段和注解。

三、Shiro配置与整合

Shiro的配置可以通过多种方式实现,包括XML、JavaConfig以及Spring的整合方式。这里我们主要介绍Spring整合Shiro的方式。

1. 配置文件

在Spring的配置文件中(通常是applicationContext.xml或基于Java的配置类),你需要配置Shiro的过滤器链、安全管理器(SecurityManager)、Realm等核心组件。

2. Realm实现

Realm是Shiro与应用安全数据之间的桥梁,你需要实现自己的Realm类,用于连接数据库,查询用户、角色和权限信息。

public class MyRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService; // 假设你有一个UserService用于操作用户数据

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 从principals中获取用户身份信息,查询用户的角色和权限
        String username = (String) principals.getPrimaryPrincipal();
        User user = userService.findUserByUsername(username);
        
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        for (Role role : user.getRoles()) { // 假设User类中有获取Role列表的方法
            info.addRole(role.getRoleName());
            for (Permission permission : role.getPermissions()) { // 假设Role类中有获取Permission列表的方法
                info.addStringPermission(permission.getPermissionName());
            }
        }
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 根据用户名查询用户信息,并进行密码比对
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        User user = userService.findUserByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("用户不存在");
        }
        
        // 假设密码已经加密存储,这里进行密码比对
        // 注意:实际开发中应使用Shiro的密码比对机制,这里仅为示例
        if (!user.getPassword().equals(new String(upToken.getPassword()))) {
            throw new IncorrectCredentialsException("密码错误");
        }
        
        // 返回AuthenticationInfo,包含用户信息和凭证信息
        return new SimpleAuthenticationInfo(username, user.getPassword(), getName());
    }
}

注意,在doGetAuthorizationInfo方法中,我们根据用户信息查询了其角色和权限信息,并将这些信息封装在SimpleAuthorizationInfo对象中返回。在doGetAuthenticationInfo方法中,我们进行了用户身份认证,包括用户名查找和密码比对。

3. Shiro过滤器链配置

在Spring MVC中,你还需要配置Shiro的过滤器链,以实现对请求的拦截和权限校验。这通常通过定义一个shiroFilterFactoryBean的Bean来完成。

@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
    shiroFilter.setSecurityManager(securityManager);
    
    // 定义过滤器链
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    filterChainDefinitionMap.put("/login/**", "anon"); // 登录请求不拦截
    filterChainDefinitionMap.put("/**", "authc, perms[user:view]"); // 其他请求需要认证和权限校验
    shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
    
    return shiroFilter;
}

在这个配置中,我们定义了两个过滤器链规则:/login/**路径下的请求不需要认证(anon),而其他所有请求都需要进行认证(authc)并具备user:view权限(perms[user:view])。

四、测试与验证

完成上述配置后,你需要编写测试用例来验证Shiro与Hibernate的集成是否成功。

推荐文章