springboot集成安全框架springsecurity

注意,在配置过滤器时 每个权限/角色配置操作前面都要写上请求路径
如: .anyRequest() 请求路径
.authenticated()//都需要认证操作 是权限/角色操作

在这里插入图片描述

三种用户认证方式(设置用户名密码的)

如果打开crsf防护需要在页面中加入下面代码

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />

加这个的目的是每次请求时都把csrf防护生成的随机token带上

第一种:通过配置文件(非查库)

应用添加security依赖后,在application配置文件中写入spring.security.user.name和spring.security.user.password即可,若注入成功 控制台不会报security框架自动生成的初始密码

# 应用名称
spring.application.name=spring-security-smalldemo
# 应用服务 WEB 访问端口
server.port=8080
#设置用户名密码方式一 配置文件
spring.security.user.name=lql
spring.security.user.password=mima

第二种 通过配置类(非查库)

在配置类中编写如下即可

package com.li.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**  设置用户名密码的第二种方式 配置类
 * @author liql
 * @date 2021/9/21
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //密码需要加密 不然报 Encoded password does not look like BCrypt 错误
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = passwordEncoder.encode("123456");
        //角色不能不设置,不然报错
        auth.inMemoryAuthentication().withUser("lql").password(password).roles("");

    }

    //不注入PasswordEncoder 会报下面的错误
    //java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

第三种 通过实现 UserDetailsService接口设置用户名密码(可查库)

分别定义一个配置类和接口实例类即可,
用户名密码查库操作可定义在该实例中只需要替换返回对象User中的参数为数据库查到的即可。

配置类

package com.li.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**  设置用户名密码的第三种方式 通过实现 userDetailsService 接口
 * @author liql
 * @date 2021/9/21
 */
@Configuration
public class SecurityConfig2 extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

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

    }

    //不注入PasswordEncoder 会报下面的错误
    //java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

用户名密码写死

package com.li.config;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 配置第三种用户密码的方式的实现类  UserDetailsService接口是security框架的
 * @author liql
 * @date 2021/9/21
 */
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //设置权限
        List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList("roles");

        //第三个参数为设置权限,不能为空。
        return new User("lql", new BCryptPasswordEncoder().encode("123"), authorityList);
    }
}

通过查库获取用户名对应的密码

参数 username为登录界面输入的用户名,把查库拿到的密码传入到返回值中,security底层会自动将查库的密码与登录界面输入的密码做校验

package com.li.config;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置第三种用户密码的方式的实现类  UserDetailsService接口是security框架的
 * @author liql
 * @date 2021/9/21
 */
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
    //定义一个安全类集合模拟数据库
    private static ConcurrentHashMap<String,String> mydb=new ConcurrentHashMap();
    static {
        mydb.put("lql", "111");
        mydb.put("xiaohong", "123");
    }

    /**
     *
     * @param username  该参数为登录界面输入的用户名
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //设置权限
        List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList("roles");

        //模拟通过数据库查密码
        String password=mydb.get(username);
        // if(查库没查到){
        //    throw new UsernameNotFoundException("用户名不存在")
        //  }

        //把数据库查到的密码传入进去 security框架底层会帮我们自动做校验 第三个参数为设置权限,不能为空。
        return new User(username, new BCryptPasswordEncoder().encode(password), authorityList);
    }
}

自定义设置登录页面

在原先的配置类中重写 void: configure(HttpSecurity http) 方法

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }

重写后

   @Override
    protected void configure(HttpSecurity http) throws Exception {
       http.formLogin().loginPage("/login.html") //登录界面
               .loginProcessingUrl("/user/login") //用户密码需要提交到的路径 该路径由security管理 不需要我们定义
               .defaultSuccessUrl("/test/index")//登录成功后跳转到的页面
               .permitAll()// 无条件允许访问 不校验权限
                .and()
               .authorizeRequests()//后面写认证配置
               .anyRequest() //任何请求
               .authenticated()//都需要认证操作
//               .antMatchers("/","/test/hello").permitAll()  //设置哪些无条件允许访问 但必须先认证然后不校验权限  
               .and()
               .csrf().disable();//关闭csrf防护 关闭跨域保护
    }

添加依赖和配置
spring.thymeleaf.prefix=classpath:/static

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

login.html
页面 username password 参数名是固定的,因为在UsernamePasswordAuthenticationFilter过滤器中明确定义了
在这里插入图片描述

<!DOCTYPE html>
<!-- 需要添加
<html  xmlns:th="http://www.thymeleaf.org">
这样在后面的th标签就不会报错
 -->
<html  xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>xx</title>
</head>
<body>


<h1>表单提交</h1>
<!-- 表单提交用户信息,注意字段的设置,直接是*{} -->
<form action="/user/login"  method="post">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    <input type="text" name="username" />
    <input type="text" name="password" />
    <input type="submit" />
</form>
</body>
</html>

登录成功跳转页面

    @GetMapping("/index")
    @ResponseBody
    public String index(){

        return "登录成功";
    }

基于权限进行控制

给用户授权

在UserDetailsService的实例类里进行授权

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //设置权限
        List<GrantedAuthority> authorityList =
                AuthorityUtils
                 //该方法   commaSeparatedStringToAuthorityList 技能设置权限又能设置角色,设置角色时加前缀 ROLE_XXX , 多个权限和角色中间用逗号隔开
                .commaSeparatedStringToAuthorityList("perm_hello1,perm_hello2");

        //模拟通过数据库查密码
        String password=mydb.get(username);
        // if(查库没查到){
        //    throw new UsernameNotFoundException("用户名不存在")
        //  }
        //把数据库查到的密码传入进去 security框架底层会帮我们自动做校验 第三个参数为设置权限和角色,不能为空。
        return new User(username, new BCryptPasswordEncoder().encode(password), authorityList);
    }

设置访问路径的权限

在配置类里

    @Override
    protected void configure(HttpSecurity http) throws Exception {
 /*      http.formLogin().loginPage("/login.html") //登录界面
               .loginProcessingUrl("/user/login") //用户密码需要提交到的路径 该路径由security管理 不需要我们定义
               .defaultSuccessUrl("/test/index")//登录成功后跳转到的页面
               .permitAll()// 无条件允许访问 但必须先认证然后不校验权限
                .and()
               .authorizeRequests()//后面写认证配置
               .anyRequest() //任何请求
               .authenticated()//都需要认证操作
//               .antMatchers("/","/test/hello").permitAll()  //设置哪些路径可以不用认证就能访问
               .and()
               .csrf().disable();//关闭csrf防护 关闭跨域保护*/

        http.formLogin().loginPage("/login.html") //登录界面
                .loginProcessingUrl("/user/login") //用户密码需要提交到的路径 该路径由security管理 不需要我们定义
                .defaultSuccessUrl("/test/index")//登录成功后跳转到的页面
                .permitAll()// 无条件允许访问 但必须先认证然后不校验权限
                .and()
                .authorizeRequests()
                .antMatchers("/test/hello")
                .hasAnyAuthority("perm_hello")//满足该权限 ,只能写单个权限
                .antMatchers("/test/hello2")
                //满足下面权限的一个即可放行
                .hasAnyAuthority("perm_hello,perm_hello2")
                .anyRequest() //任何请求
                .authenticated()//都需要认证操作
                .and()
                .csrf().disable();//关闭csrf防护 关闭跨域保护;
    }

基于角色访问

给用户设置角色

与设置权限的地方相同 ,在实例类中 设置权限的地方增加 ROLE_xxx 即可
加“ROLE_”前缀的原因是,在配置过滤器时 如写个角色为 “admin” 但是在底层会校验“ROLE_admin”;
在这里插入图片描述

  List<GrantedAuthority> authorityList =
                AuthorityUtils
                 //该方法   commaSeparatedStringToAuthorityList 技能设置权限又能设置角色,设置角色时加前缀 ROLE_XXX , 多个权限和角色中间用逗号隔开
                        //ROLE_admin 给用户设置 admin角色
                .commaSeparatedStringToAuthorityList("perm_hello1,perm_hello2,ROLE_admin");

给路径设置角色

与设置路径的地方相同 在配置类中
增加

.antMatchers("/test/hello2")
                //满足下面角色的一个即可放行
                .hasRole("admin")
                 .antMatchers("/test/hello3")
                //满足其中的一个角色即可放行
                .hasAnyRole("admin,admin2")
 @Override
    protected void configure(HttpSecurity http) throws Exception {
 /*      http.formLogin().loginPage("/login.html") //登录界面
               .loginProcessingUrl("/user/login") //用户密码需要提交到的路径 该路径由security管理 不需要我们定义
               .defaultSuccessUrl("/test/index")//登录成功后跳转到的页面
               .permitAll()// 无条件允许访问 但必须先认证然后不校验权限
                .and()
               .authorizeRequests()//后面写认证配置
               .anyRequest() //任何请求
               .authenticated()//都需要认证操作
//               .antMatchers("/","/test/hello").permitAll()  //设置哪些路径可以不用认证就能访问
               .and()
               .csrf().disable();//关闭csrf防护 关闭跨域保护*/

        http.formLogin().loginPage("/login.html") //登录界面
                .loginProcessingUrl("/user/login") //用户密码需要提交到的路径 该路径由security管理 不需要我们定义
                .defaultSuccessUrl("/test/index")//登录成功后跳转到的页面
                .permitAll()// 无条件允许访问 但必须先认证然后不校验权限
                .and()
                .authorizeRequests()
                .antMatchers("/test/hello")
                .hasAnyAuthority("perm_hello")//满足该权限 ,只能写单个权限
                .antMatchers("/test/hello2")
                //满足下面权限的一个即可放行
                .hasAnyAuthority("perm_hello,perm_hello2")
                .antMatchers("/test/hello2")
                //满足下面角色的一个即可放行
                .hasRole("admin")
                 .antMatchers("/test/hello3")
                //满足其中的一个角色即可放行
                .hasAnyRole("admin,admin2")
                .anyRequest() //任何请求
                .authenticated()//都需要认证操作
                .and()
                .csrf().disable();//关闭csrf防护 关闭跨域保护;
    }

自定义无权限时的返回页面

依然在配置过滤器的方法中加入 即可 页面
在这里插入图片描述

  //设置无权限时返回的页面
        http.exceptionHandling().accessDeniedPage("/test/unauthen");
   @GetMapping("/unauthen")
    @ResponseBody
    public String unauthen(){
        return "无权访问";
    }

退出登录

在配置类中加上如下配置即可
在这里插入图片描述

 //配置退出
        http.logout()
                .logoutUrl("/logout") //输入该url表示退出
                .logoutSuccessUrl("/test/logout")//成功退出后跳转的页面
                .permitAll();

基于注解配置

自动登录

自动登录的实现原理是:

  1. 浏览器请求登录
  2. 验证通过 给浏览器返回一个标记自动登录 token,并同时把这个token存入到数据库
  3. 下次登录 / 访问资源的时候,浏览器携带token进行请求,框架会拿到这个token与数据库存的token做对比,相同则放行,否则重新登录。

开发步骤

  1. 配置类注入数据源
//注入数据源 使用rememberme-me 时需要
    @Autowired
    private DataSource dataSource;
  1. 配置类中创建操作数据库的对象
//配置操作数据库的对象
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        //下面这个api需要导入 orm框架相关的架包 如 mybatisplus
        jdbcTokenRepository.setDataSource(dataSource);
        //下面这个api可以帮我们自动在数据库创建 rememberme-me  时需要的数据库表一般第一次使用的时候打开
        //如果表已经存在会报错
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }
  1. 在配置类过滤器中配置自动登录的配置
 .and().
                rememberMe().
                tokenRepository(persistentTokenRepository())//引入操作数据库的类
                .tokenValiditySeconds(600)//设置有效时长,单位秒
                .userDetailsService(userDetailsService)
  1. 页面要配置 name=“remember_me”的输入框
<html  xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>xx</title>
</head>
<body>
<h1>表单提交</h1>
<form action="/user/login"  method="post">
    <input type="text" name="username" />
    <input type="text" name="password" />
    <input type="checkbox"name="remember-me"title="记住密码"/>记住密码<br/>
    <input type="submit" />
</form>
</body>
</html>

完整的配置类

package com.li.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**  设置用户名密码的第三种方式 通过实现 userDetailsService 接口
 * @author liql
 * @date 2021/9/21
 */
@Configuration
public class SecurityConfig2 extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

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

    }

    //不注入PasswordEncoder 会报下面的错误
    //java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
 /*      http.formLogin().loginPage("/login.html") //登录界面
               .loginProcessingUrl("/user/login") //用户密码需要提交到的路径 该路径由security管理 不需要我们定义
               .defaultSuccessUrl("/test/index")//登录成功后跳转到的页面
               .permitAll()// 无条件允许访问 但必须先认证然后不校验权限
                .and()
               .authorizeRequests()//后面写认证配置
               .anyRequest() //任何请求
               .authenticated()//都需要认证操作
//               .antMatchers("/","/test/hello").permitAll()  //设置哪些路径可以不用认证就能访问
               .and()
               .csrf().disable();//关闭csrf防护 关闭跨域保护*/

        http.formLogin().loginPage("/login.html") //登录界面
                .loginProcessingUrl("/user/login") //用户密码需要提交到的路径 该路径由security管理 不需要我们定义
                .defaultSuccessUrl("/test/index")//登录成功后跳转到的页面
                .permitAll()// 无条件允许访问 但必须先认证然后不校验权限
                .and()
                .authorizeRequests()
                .antMatchers("/test/hello")
                .hasAnyAuthority("perm_hello")//满足该权限 ,只能写单个权限
                .antMatchers("/test/hello2")
                //满足下面权限的一个即可放行
                .hasAnyAuthority("perm_hello,perm_hello2")
                .antMatchers("/test/hello2")
                //满足下面角色即可放行
                .hasRole("admin")
                .antMatchers("/test/hello3")
                //满足其中的一个角色即可放行
                .hasAnyRole("admin,admin2")
                .anyRequest() //任何请求
                .authenticated()//都需要认证操作
                //下面是开启记住我功能的配置
                .and().
                rememberMe().
                tokenRepository(persistentTokenRepository())//引入操作数据库的类
                .tokenValiditySeconds(600)//设置有效时长,单位秒
                .userDetailsService(userDetailsService)
                .and()
                .csrf().disable();//关闭csrf防护 关闭跨域保护;

        //设置无权限时返回的页面
        http.exceptionHandling().accessDeniedPage("/test/unauthen");
        //配置退出
        http.logout()
                .logoutUrl("/logout") //输入该url表示退出
                .logoutSuccessUrl("/test/logout")//成功退出后跳转的页面
                .permitAll();
    }

    //注入数据源 使用rememberme-me 时需要,要引入mysql驱动
    @Autowired
    private DataSource dataSource;
    //配置操作数据库的对象
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        //下面这个api需要导入 orm框架相关的架包 如 mybatisplus
        jdbcTokenRepository.setDataSource(dataSource);
        //下面这个api可以帮我们自动在数据库创建 rememberme-me  时需要的数据库表一般第一次使用的时候打开
        //如果表已经存在会报错
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Vue和SpringBoot打造假日旅社管理系统》课程,将讲解如何使用Vue和SpringBoot开发这个项目,手把手演示开发流程!附赠源码、文档、数据库脚本等全部资料,提供售后答疑。 课程简介本课程讲解的是《基于 Vue 和 SpringBoot 的假日旅社管理系统》,该系统支持民宿档案、民宿新闻、民宿预定、民宿评论这四大核心业务,适用于乡村民宿企业的民宿预定业务。系统给每个民宿档案提供一个唯一标识,对民宿预定、评论等各个环节进行快速批量的数据采集,确保游客及时掌握景区民宿的真实数据,方便游客进行民宿预定。另外系统还包括员工管理、组织机构管理、文件管理、权限管理功能,给旅社企业提供更个性化的民宿管理模式。假日旅社管理系统采用了基于角色的访问控制,角色和菜单关联,一个角色可以配置多个菜单权限;然后再将用户和角色关联,一位用户可以赋予多个角色。这样用户就可以根据角色拿到该有的菜单权限,更方便旅社企业的管理人员进行权限管控。   软件技术选型前端Vue:Vue 是构建前端界面的核心框架,本系统采用 2.6.14 版本。View UI:基于 Vue.js2.0 的组件库,本系统采用 4.7.0 版本。后端Spring Boot:构建系统核心逻辑的后端框架,本系统采用 2.7.0 版本。MyBatis / MyBatis Plus:后端连接数据库的框架,本系统采用 3.5.2 版本。数据库MySQL:本项目的主数据库,本系统采用 8.0.29 版本。Redis:本系统采用基于 Windows 版本的 Redis,用于图形验证码和用户菜单权限的临时存储,采用了 5.0.14 版本。开发环境VsCode:项目前端的开发工具,使用版本为 1.68.0。IntelliJ IDEA :项目后端的开发工具,使用版本为 2021.3.2。Jdk:Java 的开发环境,使用版本为 17.0.3.1。Maven:后端项目的打包工具,使用版本为 3.6.2。NodeJs:前端项目的开发环境,使用版本为 16.13.0。 软件架构分析基于 Vue 和 SpringBoot 的假日旅社管理系统包括了系统基础模块、民宿档案模块、民宿新闻模块、民宿预定模块、民宿评论模块这五大功能模块,其架构如下图所示。  接下来,分别对五大模块进行详细介绍。系统基础模块系统基础模块,是用于支撑假日旅社管理系统的正常运行,这个模块包括了登陆注册模块、员工部门管理、菜单权限管理等。假日旅社管理系统支持用户使用账号、密码和图形验证码登陆,操作界面如下图所示。  假日旅社管理系统支持用户使用手机号、姓名、密码和图形验证码注册,操作界面如下图所示。 用户成功进入系统后,可进入到基于 Vue 和 SpringBoot 的假日旅社管理系统的首页,首页展示了当前登陆的地址、现在的时间和用户配置的常用模块,如下图所示。 接着用户点击左侧的用户管理,即可进入用户管理模块,用户管理模块的首页如下图所示。 用户可以在这个模块对系统登陆用户的档案进行维护,包括添加新用户、删除用户、编辑用户、根据姓名/部门查询用户。用户可以进入部门管理模块,管理旅社的部门数据,如下图所示。 同理用户可以进入到菜单管理模块,对系统的菜单进行管理,菜单管理模块的操作界面如下图所示。 民宿档案模块第二个模块是民宿档案模块,民宿档案就是用来管理民宿的数据,民宿档案包括民宿的名称、面积、房号、房间类型、早餐情况、价格、备注等,以下是民宿档案模块的主界面。用户可以点击顶部的“新增”按钮,进入民宿档案添加界面,添加民宿档案数据,如下图所示。 其中房间类型为下拉框单项选择,如下图所示。还有早餐情况也是下拉单选,如下图所示。 用户可以对现有的民宿档案数据进行编辑更新,只需点击每一行民宿档案数据的“编辑”按钮,即可进入民宿档案数据的编辑界面,如下图所示。 用户也可以对不需要的民宿数据进行删除操作,用户点击删除时,系统会弹出二次确认弹框,如下图所示。  民宿新闻模块第三个模块是民宿新闻模块,民宿新闻就是用来管理民宿的新闻资讯,包含的功能如下所示。 民宿新闻包括民宿的名称、面积、房号、房间类型、早餐情况、价格、备注等,以下是民宿新闻模块的主界面,其中的图片仅供测试样例使用。用户可以点击顶部的“新增”按钮,进入民宿新闻添加界面,添加民宿新闻数据,如下图所示。 新闻描述字段采用了 ueditor 富文本编辑器,这是由百度 web 前端研发部开发的所见即所得的开源富文本编辑器,具有轻量、可定制、用户体验优秀等特点,基于 MIT 开源协议,所有源代码可自由修改和使用。 用户可以对现有的民宿新闻数据进行编辑更新,只需点击每一行民宿新闻数据的“编辑”按钮,即可进入民宿新闻数据的编辑界面,如下图所示。 民宿预定模块第四个模块是民宿预定模块,旅客可以在民宿预定模块中预定民宿,达到旅客的住宿目的,民宿预定模块包含的功能如下所示。民宿预定包括了预定民宿 ID、预定民宿名称、预定日期、下单时间、下单人 ID、下单人姓名、价格、是否付款、下单备注等字段,旅客首先进入民宿档案模块,可以看到每一行民宿数据都有一个预约按钮,如下图所示。 如用户点击 1 幢 102 民宿的预约按钮后,会弹出预约确认框,需要输入预约的日期,日期表单默认选择今日,如下图所示。 旅客需要点击“确认预约”按钮,完成预约操作,系统给与“预约成功”提示,如下图所示。 预约成功后,旅客可以从民宿预定模块中进行查询,如下图所示。 最后旅客进行付款操作,点击每一行右侧的付款按钮,如下图所示。支付完成后,系统将预定单的支付状态改为付款,预定流程结束,如下图所示。 民宿评论模块 第五个模块是民宿预定模块,旅客可以在民宿预定结束后评论民宿,以帮助更多的人了解民宿,民宿评论模块包含的功能如下所示。 民宿评论包括了民宿名称、民宿 ID、评论时间、评论内容、评论人 ID、评论人姓名等字段,旅客首先进入民宿档案模块,可以看到每一行民宿数据都有一个评论按钮,如下图所示。 旅客点击评论后,系统给与弹框反馈,如下图所示。  用户输入评论内容后,点击确认评论按钮,即可完成评论操作,如下图所示。  旅客评论后,即可在民宿评论模块中查看此评论数据,如下图所示。 也可以在民宿模块中,双击民宿数据查看评论信息,如下图所示。 项目总结本软件是基于 Vue 和 SpringBoot 的假日旅社管理系统,包含了民宿档案、民宿新闻、民宿预定、民宿评论这四个功能模块。 开发本系统的目的,就是为了帮助旅游景点的民宿企业提高民宿管理效率,降低人力成本,让旅游景点的民宿企业获得更多的经济效益。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值