欢迎访问宙启技术站
智能推送

基于springboot+bootstrap+mysql+redis怎么搭建完整的权限架构

发布时间:2023-05-15 15:40:17

在基于Spring Boot、Bootstrap、MySQL和Redis搭建完整的权限架构之前,我们需要了解一些相关的基础知识。

1. Spring Boot:Spring Boot是Spring框架的一种扩展,它通过提供默认配置,简化了Spring应用程序的开发和部署。 Spring Boot通过将Spring框架主要的特性和功能提供给应用程序开发人员来集成Spring框架。

2. Bootstrap:Bootstrap是一个开源的前端框架,它使用HTML、CSS和JavaScript来开发基于Web的应用程序。Bootstrap提供了响应式设计、UI组件、JavaScript插件等功能。

3. MySQL:MySQL是一个开源的关系型数据库管理系统,它的主要特点是高效、可靠、安全和易维护等。

4. Redis:Redis是一个高性能的键值对数据库。它支持多种数据结构,包括字符串、哈希表、列表、集合等,它还支持多种持久化机制,包括RDB、AOF等。

接下来,我们将详细介绍如何搭建完整的权限架构。

1. 数据库设计

在MySQL中创建以下表格:

用户表(user):存储系统中的用户信息。

字段名称 | 类型 | 描述 

---|---|---

id | Long | 用户ID

username | varchar(255) | 用户名

password | varchar(255) | 密码

name | varchar(255) | 姓名

email | varchar(255) | 邮箱

enabled | boolean | 是否启用

locked | boolean | 是否锁定

角色表(role):存储系统中的角色信息。

字段名称 | 类型 | 描述 

---|---|---

id | Long | 角色ID

name | varchar(255) | 角色名

权限表(permission):存储系统中的权限信息。

字段名称 | 类型 | 描述 

---|---|---

id | Long | 权限ID

name | varchar(255) | 权限名

url | varchar(255) | 权限URL

用户角色关联表(user_role):存储用户和角色之间的关联关系。

字段名称 | 类型 | 描述 

---|---|---

id | Long | 主键ID

user_id | Long | 用户ID

role_id | Long | 角色ID

角色权限关联表(role_permission):存储角色和权限之间的关联关系。

字段名称 | 类型 | 描述 

---|---|---

id | Long | 主键ID

role_id | Long | 角色ID

permission_id | Long | 权限ID

2. 后台代码实现

(1)编写实现用户认证和授权的代码

我们使用Spring Security来实现用户认证和授权。我们创建一个类(SecurityConfig)并在其中配置Spring Security的认证和授权,如下所示:

@Configuration

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired

  private UserDetailsService userDetailsService;

  @Autowired

  private PasswordEncoder passwordEncoder;

  @Override

  protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()

        .antMatchers("/", "/home", "/register").permitAll()

        .antMatchers("/admin/**").hasRole("ADMIN")

        .anyRequest().authenticated()

        .and()

        .formLogin()

        .loginPage("/login")

        .permitAll()

        .and()

        .logout()

        .permitAll();

  }

  @Override

  protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);

  }

}

在上面的代码中,我们定义了以下内容:

- 对没有被保护的URL进行授权

- 对被保护的URL进行授权,必须具有ADMIN角色

- 登录页面的设置

- 添加注销特性

(2)编写实现用户认证和授权的服务

我们创建一个类(UserDetailsServiceImpl)并实现UserDetailsService的loadUserByUsername方法,如下所示:

@Service

public class UserDetailsServiceImpl implements UserDetailsService {

  @Autowired

  private UserDao userDao;

  @Override

  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    User user = userDao.findByUsername(username);

    if (user == null) {

      throw new UsernameNotFoundException("User not found with username: " + username);

    }

    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    for (Role role : user.getRoles()) {

      authorities.add(new SimpleGrantedAuthority(role.getName()));

      for (Permission permission : role.getPermissions()) {

        authorities.add(new SimpleGrantedAuthority(permission.getName()));

      }

    }

    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.isEnabled(), !user.isLocked(),

        true, true, authorities);

  }

}

在上面的代码中,我们实现了loadUserByUsername方法。首先我们在用户表(user)中通过用户名(username)查找用户信息,如果用户不存在,则抛出UsernameNotFoundException异常。然后我们通过用户和角色的关联关系查找用户所拥有的所有角色以及这些角色所拥有的权限,并将这些信息转换成GrantedAuthority的实例。

(3)实现数据访问层

我们创建一个类(UserDao)实现CRUD操作,如下所示:

@Repository

public interface UserDao extends JpaRepository<User, Long> {

  User findByUsername(String username);

}

在上面的代码中,我们使用Spring Data JPA提供的方法实现对用户表(user)的CRUD操作,并提供了findByUsername方法来根据用户名查找用户信息。

(4)实现角色和权限

我们创建两个类(Role和Permission)来表示角色和权限。这些类分别对应角色表(role)和权限表(permission)。

@Entity

public class Role {

  @Id

  @GeneratedValue(strategy = GenerationType.IDENTITY)

  private Long id;

  @Column(nullable = false)

  private String name;

  @OneToMany(mappedBy = "role", cascade = CascadeType.ALL, fetch = FetchType.LAZY)

  private List<UserRole> userRoles = new ArrayList<UserRole>();

  @ManyToMany(fetch = FetchType.LAZY)

  @JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "permission_id"))

  private List<Permission> permissions = new ArrayList<Permission>();

  // setters and getters

}

@Entity

public class Permission {

  @Id

  @GeneratedValue(strategy = GenerationType.IDENTITY)

  private Long id;

  @Column(nullable = false)

  private String name;

  @Column(nullable = false)

  private String url;

  @ManyToMany(mappedBy = "permissions", fetch = FetchType.LAZY)

  private List<Role> roles = new ArrayList<Role>();

  // setters and getters

}

在上面的代码中,我们使用JPA注解来定义实体类和关联关系。

(5)实现UserRole

我们创建一个类(UserRole)来表示用户和角色之间的关联关系,如下所示:

@Entity

public class UserRole {

  @Id

  @GeneratedValue(strategy = GenerationType.IDENTITY)

  private Long id;

  @ManyToOne(fetch = FetchType.LAZY)

  @JoinColumn(name = "user_id")

  private User user;

  @ManyToOne(fetch = FetchType.LAZY)

  @JoinColumn(name = "role_id")

  private Role role;

  // setters and getters

}

在上面的代码中,我们使用JPA注解来定义实体类和关联关系。

3. 前台代码实现

我们使用Bootstrap和Thymeleaf来实现前台页面。我们创建以下页面:

(1)首页页面(home.html)

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

  <meta charset="UTF-8">

  <title>Home</title>

</head>

<body>

  <h1>Welcome to Home Page</h1>

  <p><a href="/login">Login</a></p>

  <p><a href="/register">Register</a></p>

</body>

</html>

(2)登录页面(login.html)

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

  <meta charset="UTF-8">

  <title>Login Page</title>

</head>

<body>

  <h1>Login Page</h1>

  <form th:action="@{/login}" method="post">

    <label>Username : </label><input type="text" name="username" /><br/>