基于SpringBoot + MyBatis的前后端分离实现在线办公系统

本文介绍了基于SpringBoot和MyBatis开发的在线办公系统的实现,包括登录模块、权限管理、Swagger2配置、验证码功能、Redis缓存、RabbitMQ邮件发送以及在线聊天功能。系统采用JWT处理Token,使用SpringSecurity进行安全配置,使用Redis存储用户菜单信息,并通过RabbitMQ发送新员工欢迎邮件。
摘要由CSDN通过智能技术生成

在线办公系统

目录

1.开发环境的搭建及项目介绍

本项目目的是实现中小型企业的在线办公系统,云E办在线办公系统是一个用来管理日常的办公事务的一个系统

使用SpringSecurity做安全认证及权限管理,Redis做缓存,RabbitMq做邮件的发送,使用EasyPOI实现对员工数据的导入和导出,使用WebSocket做在线聊天

使用验证码登录

在这里插入图片描述

页面展示:

在这里插入图片描述

  1. 添加依赖

  2. 使用MyBatis的AutoGenerator自动生成mapper,service,Controller

2.登录模块及配置框架搭建

<1>Jwt工具类及对Token的处理

1.1根据用户信息生成Token
  1. 定义JWT负载中用户名的Key以及创建时间的Key

    //用户名的key
    private static final String CLAIM_KEY_USERNAME=“sub”;
    //签名的时间
    private static final String CLAIM_KEY_CREATED=“created”;

  2. 从配置文件中拿到Jwt的密钥和失效时间

    /**

    • @Value的值有两类:
    • ① ${ property : default_value }
    • ② #{ obj.property? :default_value }
    • 第一个注入的是外部配置文件对应的property,第二个则是SpEL表达式对应的内容。 那个
    • default_value,就是前面的值为空时的默认值。注意二者的不同,#{}里面那个obj代表对象。
      */
      //JWT密钥
      @Value(“${jwt.secret}”)
      private String secret;

    //JWT失效时间
    @Value(“${jwt.expiration}”)
    private Long expiration;

  3. 根据用户信息UserDetials生成Token

    /**

    • 根据用户信息生成Token
    • @param userDetails
    • @return
      */
      public String generateToken(UserDetails userDetails){
      //荷载
      Map<String,Object> claim=new HashMap<>();
      claim.put(CLAIM_KEY_USERNAME,userDetails.getUsername());
      claim.put(CLAIM_KEY_CREATED,new Date());
      return generateToken(claim);
      }

    /**

    • 根据负载生成JWT Token
    • @param claims
    • @return
      */
      private String generateToken(Map<String,Object> claims) {
      return Jwts.builder()
      .setClaims(claims)
      .setExpiration(generateExpirationDate())//添加失效时间
      .signWith(SignatureAlgorithm.HS512,secret)//添加密钥以及加密方式
      .compact();
      }

    /**

    • 生成Token失效时间 当前时间+配置的失效时间
    • @return
      /
      private Date generateExpirationDate() {
      return new Date(System.currentTimeMillis()+expiration
      1000);
      }
1.2根据Token生成用户名
/**
 * 根据Token生成用户名
 * @param token
 * @return
 */
public String getUsernameFormToken(String token){
    String username;
    //根据Token去拿荷载
    try {
        Claims claim=getClaimFromToken(token);
        username=claim.getSubject();//获取用户名
    } catch (Exception e) {
        e.printStackTrace();
        username=null;
    }
    return username;
}

/**
 * 从Token中获取荷载
 * @param token
 * @return
 */
private Claims getClaimFromToken(String token) {
    Claims claims=null;
    try {
        claims=Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return claims;
}
1.3判断Token是否有效
/**
 * 判断Token是否有效
 * Token是否过期
 * Token中的username和UserDetails中的username是否一致
 * @param token
 * @param userDetails
 * @return
 */
public boolean TokenIsValid(String token,UserDetails userDetails){
    String username = getUsernameFormToken(token);
    return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}

/**
 * 判断Token是否过期
 * @param token
 * @return
 */
private boolean isTokenExpired(String token) {
    //获取Token的失效时间
    Date expireDate=getExpiredDateFromToken(token);
    //在当前时间之前,则失效
    return expireDate.before(new Date());
}

/**
 * 获取Token的失效时间
 * @param token
 * @return
 */
private Date getExpiredDateFromToken(String token) {
    Claims claims = getClaimFromToken(token);
    return claims.getExpiration();
}
1.4判断Token是否可以被刷新
/**
 * 判断token是否可用被刷新
 * 如果已经过期了,则可用被刷新,未过期,则不可用被刷新
 * @param token
 * @return
 */
public boolean canRefresh(String token){
    return !isTokenExpired(token);
}
1.5刷新Token,获取新的Token
/**
 * 刷新Token
 * @param token
 * @return
 */
public String refreshToken(String token){
    Claims claims=getClaimFromToken(token);
    claims.put(CLAIM_KEY_CREATED,new Date());
    return generateToken(claims);
}

<2>登录功能的实现

  • Controller层

    @ApiOperation(value = "登录之后返回token")
    @PostMapping("/login")
    //AdminLoginParam 自定义登录时传入的对象,包含账号,密码,验证码 
    public RespBean login(@RequestBody AdminLoginParam adminLoginParam, HttpServletRequest request){
        return adminService.login(adminLoginParam.getUsername(),adminLoginParam.getPassword(),adminLoginParam.getCode(),request);
    }
    
  • Service层

    /**
     * 登录之后返回token
     * @param username
     * @param password
     * @param request
     * @return
     */
    @Override
    public RespBean login(String username, String password,String code, HttpServletRequest request) {
        String captcha = (String)request.getSession().getAttribute("captcha");//验证码功能,后面提到
        //验证码为空或匹配不上
        if((code == null || code.length()==0) || !captcha.equalsIgnoreCase(code)){
            return RespBean.error("验证码错误,请重新输入");
        }
    
        //通过username在数据库查出这个对象
        //在SecurityConfig配置文件中,重写了loadUserByUsername方法,返回了userDetailsService Bean对象,使用我们自己的登录逻辑
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        //如果userDetails为空或userDetails中的密码和传入的密码不相同
        if (userDetails == null||!passwordEncoder.matches(password,userDetails.getPassword())){
            return RespBean.error("用户名或密码不正确");
        }
        //判断账号是否可用
        if(!userDetails.isEnabled()){
            return RespBean.error("该账号已经被禁用,请联系管理员");
        }
    
        //更新登录用户对象,放入security全局中,密码不放
        UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    
        //生成token
        String token = jwtTokenUtil.generateToken(userDetails);
        Map<String,String> tokenMap=new HashMap<>();
        tokenMap.put("token",token);
        tokenMap.put("tokenHead",tokenHead);//tokenHead,从配置文件yml中拿到的token的请求头 == Authorization
        return RespBean.success("登陆成功",tokenMap);//将Token返回
    }
    

<3>退出登录

退出登录功能由前端实现,我们只需要返回一个成功信息即可

@ApiOperation(value = "退出登录")
@PostMapping("/logout")
/**
 * 退出登录
 */
public RespBean logout(){
    return RespBean.success("注销成功");
}

<4>获取当前登录用户信息

  • Controller层

     @ApiOperation(value = "获取当前登录用户的信息")
        @GetMapping("/admin/info")
        public Admin getAdminInfo(Principal principal){
            //可通过principal对象获取当前登录对象
            if(principal == null){
                return null;
            }
            //当前用户的用户名
            String username = principal.getName();
            Admin admin= adminService.getAdminByUsername(username);
            //不能返回前端用户密码,设置为空
            admin.setPassword(null);
            //将用户角色返回
            admin.setRoles(adminService.getRoles(admin.getId()));
            return admin;
        }
    
    </
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在现代化的软件开发中,前后端分离是一种较为流行的开发模式,因为这种模式具有很多优点:增加了系统的可扩展性、提高了开发效率、让前端人员和后端人员更专注于自己的领域等等。基于springboot和vue,我来介绍一下如何实现宿舍管理系统前后端分离开发。 首先,我们需要搭建好springboot和vue的开发环境。接着,创建springboot项目,并集成mybatis等技术实现基本的后端功能。然后,使用vue-cli创建前端项目,并引入axios、vue-router等技术实现前端页面的开发和数据请求。在这一过程中,我们要注意前后端分离的原则,即前端和后端应该各自独立运行,可以分别部署在不同的服务器上,通过http接口进行通信。 接下来,我们就可以开始对宿舍管理系统进行开发了。我们可以先完成一些基本的功能,如登录、注册、修改密码等。接着,再逐步开发宿舍相关的功能,如学生信息管理、宿舍信息管理、宿舍住宿管理等等。在这个过程中,需要注意前后端的数据传输方式。由于是前后端分离模式前端需要发送http请求给后端,后端接收请求后返回json格式的数据,前端再根据返回的数据进行渲染。 最后,我们可以对系统进行测试,并部署到服务器上进行实际使用。这样,我们就可以享受到前后端分离带来的诸多好处,如便于维护、快速迭代、高效沟通等。同时,我们也需要注意系统的安全性,如对登录信息进行加密、防止sql注入等措施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值