java中的通用权限管理设计(推荐)

Java中的通用权限管理设计(推荐)

简介

在Java应用程序开发过程中,通用权限管理设计可以有效地管理系统内不同用户的权限,做到安全可靠地管理用户访问数据的安全性和可靠性,避免了系统访问被恶意用户攻击,数据泄露和其他相关问题的出现。

设计

本文推荐一种常见的通用权限管理设计方案,使用RBAC(Role Based Access Control)模型,该模型通过将用户的角色和权限组织成组和子组,使得用户所拥有的所有角色都能够赋予他相应的访问权限。并在访问数据时,针对用户的权限进行数据过滤,保障了数据的安全性。

设计思路

  • 用户(User):指系统内所有的用户。
  • 角色(Role):指是系统内所有可能具有的用户角色,如:管理员、普通用户等。
  • 权限(Permission):系统内所有可以进行操作的权限集合。
  • 资源(Resource):代表被控制的对象,可以是系统内的任何对象或操作,如:一个文件、一个应用、一张表等。
  • 当用户在系统中进行某个操作时,首先会向系统发起申请,系统根据该用户所拥有的角色和权限集合,判断是否具有该操作的访问权限。如果用户拥有访问权限,则可以进行该操作;如果用户没有访问权限,则返回访问失败。

设计实现

在Java程序开发中,可以使用Spring Security框架进行通用权限管理的实现, 其中,Spring Security的核心在于将安全拦截器链绑定到Spring应用程序上,并使用适当的管理器向拦截器链提供身份验证和权限控制信息。

1. 引入Maven依赖

在项目的pom.xml文件中添加Spring Security相关的依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-taglibs</artifactId>
        <version>4.2.3.RELEASE</version>
    </dependency>
</dependencies>

2. 配置Spring Security

在工程中创建 Spring Security 的配置类,继承 WebSecurityConfigurerAdapter 类,并覆盖其中的几个方法:


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsServiceImpl;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 忽略 /login 接口的 CSRF 验证
        http.csrf().ignoringAntMatchers("/login");

        http.authorizeRequests()
            .antMatchers("/admin").hasRole("ADMIN")
            .antMatchers("/user").hasAnyRole("ADMIN", "USER")
            .anyRequest().permitAll();

        // 配置登录页面和登录接口
        http.formLogin()
            .loginPage("/login").defaultSuccessURL("/")
            .failureUrl("/login?error").permitAll();

        http.logout().logoutSuccessUrl("/login?logout");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServiceImpl);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

3. 创建授权服务

在工程中定义 UserDetailsServiceImpl 类,实现 UserDetailsService 接口:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (null == user) {
            throw new UserNotFoundException("用户不存在");
        }

        Collection<GrantedAuthority> grantedAuthorities = new HashSet<>();
        List<Role> roles = roleRepository.findByUserId(user.getId());
        for (Role role : roles) {
            grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
        }

        return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
    }
}

4. 数据库表结构设计

设计系统中对应的用户、角色和权限表,并通过表与表之间的关联来实现权限管控和角色与权限的逻辑关系。

CREATE TABLE `t_user` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `username` varchar(100) NOT NULL COMMENT '登录名',
    `password` varchar(256) NOT NULL COMMENT '密码',
    `email` varchar(100) NOT NULL COMMENT '邮箱',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

CREATE TABLE `t_role` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `name` varchar(50) NOT NULL COMMENT '角色名称',
    `user_id` bigint(20) NOT NULL COMMENT '用户ID',
    PRIMARY KEY (`id`),
    KEY `idx_user_role` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';

CREATE TABLE `t_permission` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `code` varchar(50) NOT NULL COMMENT '权限编码',
    `name` varchar(50) NOT NULL COMMENT '权限名称',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表';

CREATE TABLE `t_role_permission` (
    `role_id` bigint(20) NOT NULL COMMENT '角色ID',
    `permission_id` bigint(20) NOT NULL COMMENT '权限ID',
    PRIMARY KEY (`role_id`, `permission_id`),
    KEY `idx_ROLE_ID` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色权限关联表';

示例

示例1: 演示用户角色授权

在上面的代码示例中,我们定义了 RoleRepository 接口用于操作角色表,定义 PermissionRepository 接口用于操作权限表。下面展示如何定义这两个接口。其中,Role 对应角色表,Permission 对应权限表。

@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {

    List<Role> findByUserId(Long userId);
}

@Repository
public interface PermissionRepository extends JpaRepository<Permission, Long> {
}

在完成实现以上的接口之后,可以修改 UserDetailsServiceImpl 的实现方式,在其中加入角色权限的赋值代码。示例代码如下:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userRepository.findByUsername(username);
    if (null == user) {
        throw new UserNotFoundException("用户不存在");
    }

    Collection<GrantedAuthority> grantedAuthorities = new HashSet<>();
    List<Role> roles = roleRepository.findByUserId(user.getId());
    for (Role role : roles) {
        grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
        List<Permission> permissions = permissionRepository.findByRoleId(role.getId());
        for (Permission permission : permissions) {
            grantedAuthorities.add(new SimpleGrantedAuthority(permission.getCode()));
        }
    }

    return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
}

在以上代码完成之后,可以在代码中分配角色和权限实现访问控制。具体代码示例如下:

// 定义角色列表
List<Role> roles = new ArrayList<>();
Role role = new Role();
role.setName("ADMIN");
role.setUserId(user.getId());
roles.add(role);

// 保存角色
List<Role> savedRoles = roleRepository.saveAll(roles);

// 定义用户权限列表
List<Permission> permissions = new ArrayList<>();
Permission permission = new Permission();
permission.setCode("USER_QUERY");
permission.setName("用户查询");
permissions.add(permission);

// 将权限赋给角色
List<RolePermission> rolePermissions = new ArrayList<>();
for (Role savedRole : savedRoles) {
    for (Permission savedPermission : savedPermissions) {
        RolePermission rolePermission = new RolePermission();
        rolePermission.setPermissionId(savedPermission.getId());
        rolePermission.setRoleId(savedRole.getId());
        rolePermissions.add(rolePermission);
    }
}
rolePermissionRepository.saveAll(rolePermissions);

// 查询分配的权限
List<Role> userRoles = roleRepository.findByUserId(user.getId());
for (Role userRole : userRoles) {
    List<Permission> userPermissions = permissionRepository.findByRoleId(userRole.getId());
    for (Permission permission : userPermissions) {
        System.out.println(permission);
    }
}

示例2: 演示数据过滤

在Spring Security应用程序中,通常可以使用数据过滤技术实现访问控制,以防止用户访问未授权的数据。例如,在一个在线银行系统中,某个用户只能访问自己名下的账户,而不能访问其他用户的账户。下面是一个搭配Spring Data JPA的简单示例:

(1)定义 JPA 查询接口

public interface UserAccountRepositoryCustom {

    List<UserAccount> findByUser(User user);

}

(2)实现 JPA 查询接口

@Component
public class UserAccountRepositoryImpl implements UserAccountRepositoryCustom {

    @Autowired
    UserAccountRepository userAccountRepository;

    @Override
    public List<UserAccount> findByUser(User user) {
        final QUserAccount qUserAccount = QUserAccount.userAccount;
        return new JPAQuery<>(entityManager)
            .from(qUserAccount)
            .where(qUserAccount.user.eq(user))
            .fetch();
    }
}

在以上代码中,QUserAccount 表示JPA查询实体,qUserAccount.user 表示其中的用户字段。

(3)在Service中使用

@Service
@Transactional(readOnly = true)
public class UserAccountServiceImpl implements UserAccountService {

    @Autowired
    UserAccountRepository userAccountRepository;

    @Autowired
    UserAccountRepositoryCustom userAccountRepositoryCustom;

    @Override
    public List<UserAccount> findAll() {
        User user = getLoginUser();
        return userAccountRepositoryCustom.findByUser(user);
    }
}

在以上代码中, getLoginUser() 方法获取当前登录用户信息,通过调用 userAccountRepositoryCustom.findByUser(user) 方法获取当前登录用户账户信息,实现了数据过滤的功能。

小结

本文介绍了一种通用权限管理设计方案,使用RBAC(Role Based Access Control)模型,通过将用户的角色和权限组织成组和子组,实现了对用户权限的控制,并在访问数据时,通过数据过滤实现了对用户数据权限的管控。同时,还给出了在Spring Security框架下实现通用权限管理的实现方式,并提供了代码示例和完整的表结构设计。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java中的通用权限管理设计(推荐) - Python技术站

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

相关文章

  • SpringMVC请求参数的使用总结

    SpringMVC请求参数的使用总结 在 SpringMVC 中,我们经常需要获取请求参数,包括 GET 请求和 POST 请求。本文将详细讲解 SpringMVC 请求参数的使用,包括如何获取 GET 请求参数、POST 请求参数、路径参数和请求头参数,并提供两个示例说明。 获取 GET 请求参数 在 SpringMVC 中,我们可以使用 @Request…

    Java 2023年5月18日
    00
  • springboot拦截器过滤token,并返回结果及异常处理操作

    下面我将为你详细讲解如何使用Spring Boot实现拦截器过滤Token并返回结果及异常处理操作。 什么是拦截器及Token认证 在Spring Boot中,拦截器是一种非常常用的组件,它可以拦截请求,进行一些处理,并执行相应的操作。Token认证是指在用户登录成功后,服务器会生成一个Token并返回给客户端,客户端在以后的请求中携带这个Token用于鉴权…

    Java 2023年5月19日
    00
  • scala 操作数据库的方法

    Scala操作数据库的方法 Scala是一门面向对象的静态类型编程语言,和Java一样,也是常用语言之一。Scala在Java语言基础上融入了面向对象和函数式编程的特性,并且Scala具有更为简洁的语法设计,在Java编写的代码中,依赖于Hibernate、Mybatis等ORM框架将内存中的类实例映射到数据库中,而Scala语言一般会使用Slick框架来进…

    Java 2023年6月16日
    00
  • jboss( WildFly)上运行 springboot程序的步骤详解

    下面是详细讲解 JBoss(WildFly)上运行Spring Boot程序的步骤: 1. 创建Spring Boot项目 首先,需要在电脑上安装JDK和Maven构建工具。接着,可以使用Spring Initializr来创建一个新的Spring Boot项目,可以参考以下步骤: 打开浏览器,进入 http://start.spring.io/ 选择相关的…

    Java 2023年5月19日
    00
  • JAVA多线程之中断机制stop()、interrupted()、isInterrupted()

    Java多线程之中断机制stop()、interrupted()、isInterrupted() 什么是中断机制? 在Java多线程编程中,中断机制是一种线程协作机制。由于线程的正常执行过程中,往往需要等待I/O操作或其它原因,这些等待过程可能会导致程序执行过程被阻塞。因此,一些长时间的阻塞操作如果不能在合理的时间内得到响应,就需要使用中断机制进行打断。通过…

    Java 2023年5月19日
    00
  • 什么是同步代码块?

    以下是关于同步代码块的完整使用攻略: 同步代码块 同步代码块是指在多线程编程中,使用 synchronized 关键字来实现对共享资源的访问控制的一种方式。同步代码块可以将需要同步的代码块包裹起来,从而保证同一时间只有一个线程可以访问共享资源,避免线程之间的竞争和冲突。 同步代码块的语法格式如下: synchronized (object) { // 需要同…

    Java 2023年5月12日
    00
  • java操作mysql实现增删改查的方法

    Java操作MySQL实现增删改查的方法完整攻略 1. 环境准备 在Java项目中,我们需要使用JDBC来操作MySQL数据库,因此需要引入MySQL的JDBC驱动包。以Maven项目为例,我们可以在pom.xml文件中加入以下依赖: <dependency> <groupId>mysql</groupId> <ar…

    Java 2023年5月20日
    00
  • uni-app 微信小程序授权登录的实现步骤

    下面是详细讲解“uni-app 微信小程序授权登录的实现步骤”的完整攻略: 一、前置条件 在进行微信小程序授权登录之前,要确保以下几个前置条件已经满足: 已经注册微信小程序开发者账号,并创建了一个小程序。 在小程序后台设置了合法的“授权域名”。 在小程序后台开启了“用户信息”,并获取了对应的“AppID”和“AppSecret”。 二、授权登录实现步骤 接下…

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