Ruoyi若依前后端分离框架【若依登录详细过程】

这篇具有很好参考价值的文章主要介绍了Ruoyi若依前后端分离框架【若依登录详细过程】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文主要写RuoYi项目前端登录流程

后端包含ruoyi-admin,ruoyi-common,ruoyi-framework等多个模块,ruoyi-admin为启动模块。先看一下ruoyi-admin/src/main/application.yml配置文件。

# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8080

指定了服务端启动的端口8080。我们运行ruoyi-admin/src/main/java/com/ruoyi/
RuoYiApplication.java即可启动后端,监听8080端口。
我们回到前端的登录界面。 views/login.vue

<template>
  <div class="login">
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
      <h3 class="title">若依后台管理系统</h3>
      <el-form-item prop="username">
        <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
          <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
        </el-input>
      </el-form-item>
      <el-form-item prop="password">
        <el-input
          v-model="loginForm.password"
          type="password"
          auto-complete="off"
          placeholder="密码"
          @keyup.enter.native="handleLogin"
        >
          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
        </el-input>
      </el-form-item>
      <el-form-item prop="code">
        <el-input
          v-model="loginForm.code"
          auto-complete="off"
          placeholder="验证码"
          style="width: 63%"
          @keyup.enter.native="handleLogin"
        >
          <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
        </el-input>
        <div class="login-code">
          <img :src="codeUrl" @click="getCode" class="login-code-img"/>
        </div>
      </el-form-item>
      <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
      <el-form-item style="width:100%;">
        <el-button
          :loading="loading"
          size="medium"
          type="primary"
          style="width:100%;"
          @click.native.prevent="handleLogin"
        >
          <span v-if="!loading">登 录</span>
          <span v-else>登 录 中...</span>
        </el-button>
      </el-form-item>
    </el-form>
    <!--  底部  -->
    <div class="el-login-footer">
      <span>Copyright © 2018-2020 ruoyi.vip All Rights Reserved.</span>
    </div>
  </div>
</template>

<script>
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from '@/utils/jsencrypt'

export default {
  name: "Login",
  data() {
    return {
      codeUrl: "",
      cookiePassword: "",
      loginForm: {
        username: "admin",
        password: "admin123",
        rememberMe: false,
        code: "",
        uuid: ""
      },
      loginRules: {
        username: [
          { required: true, trigger: "blur", message: "用户名不能为空" }
        ],
        password: [
          { required: true, trigger: "blur", message: "密码不能为空" }
        ],
        code: [{ required: true, trigger: "change", message: "验证码不能为空" }]
      },
      loading: false,
      redirect: undefined
    };
  },
  watch: {
    $route: {
      handler: function(route) {
        this.redirect = route.query && route.query.redirect;
      },
      immediate: true
    }
  },
  created() {
    this.getCode();
    this.getCookie();
  },
  methods: {
    getCode() {
      getCodeImg().then(res => {
        this.codeUrl = "data:image/gif;base64," + res.img;
        this.loginForm.uuid = res.uuid;
      });
    },
    getCookie() {
      const username = Cookies.get("username");
      const password = Cookies.get("password");
      const rememberMe = Cookies.get('rememberMe')
      this.loginForm = {
        username: username === undefined ? this.loginForm.username : username,
        password: password === undefined ? this.loginForm.password : decrypt(password),
        rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
      };
    },
    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true;
          if (this.loginForm.rememberMe) {
            Cookies.set("username", this.loginForm.username, { expires: 30 });
            Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
            Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
          } else {
            Cookies.remove("username");
            Cookies.remove("password");
            Cookies.remove('rememberMe');
          }
          this.$store
            .dispatch("Login", this.loginForm)
            .then(() => {
              this.$router.push({ path: this.redirect || "/" });
            })
            .catch(() => {
              this.loading = false;
              this.getCode();
            });
        }
      });
    }
  }
};
</script>

页面加载前,created()调用this.getCode()和this.getCookie()获取验证码和cookie。这里不详细说明。我们重点关注下handleLogin登录函数。this. r e f s . l o g i n F o r m . v a l i d a t e 判 断 用 户 名 、 密 码 和 验 证 码 的 合 法 性 。 t h i s . l o g i n F o r m . r e m e m b e r M e 判 断 是 否 选 择 了 记 住 密 码 。 如 果 记 住 密 码 , 我 们 把 用 户 名 密 码 存 进 c o o k i e , 下 次 跳 到 登 录 界 面 就 不 需 要 输 用 户 名 密 码 。 如 果 不 选 择 记 住 密 码 , 将 清 空 c o o k i e , 下 次 跳 到 登 录 界 面 需 要 手 动 输 入 用 户 名 和 密 码 。 t h i s . refs.loginForm.validate判断用户名、密码和验证码的合法性。this.loginForm.rememberMe判断是否选择了记住密码。如果记住密码,我们把用户名密码存进cookie,下次跳到登录界面就不需要输用户名密码。如果不选择记住密码,将清空cookie,下次跳到登录界面需要手动输入用户名和密码。 this. refs.loginForm.validatethis.loginForm.rememberMecookiecookiethis.store.dispatch(“Login”, this.loginForm),这里是我们最需要关注的地方。调用store里的Login对应的函数,把loginForm作为参数。我们跳到src/store/modules/user.js。

import { login, logout, getInfo } from '@/api/login'
......
actions: {
    // 登录
    Login({ commit }, userInfo) {
      const username = userInfo.username.trim()
      const password = userInfo.password
      const code = userInfo.code
      const uuid = userInfo.uuid
      return new Promise((resolve, reject) => {
        login(username, password, code, uuid).then(res => {
          setToken(res.token)
          commit('SET_TOKEN', res.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },
    ......
 }

这里新建了一个Promise,调用了login函数,login函数是从@/api/login引入的。我们再跳到src/api/login.js看一下这个函数:

// 登录方法
export function login(username, password, code, uuid) {
 const data = {
   username,
   password,
   code,
   uuid
 }
 return request({
   url: '/login',
   method: 'post',
   data: data
 })
}

这里构建了一个ajax的POST请求,url为/login,data为用户名、密码、验证码的结构数据。我们再简单看一下request对应的src/utils/request.js。

// 创建axios实例
const service = axios.create({
 // axios中请求配置有baseURL选项,表示请求URL公共部分
 baseURL: process.env.VUE_APP_BASE_API,
 // 超时
 timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
 // 是否需要设置 token
 const isToken = (config.headers || {}).isToken === false
 if (getToken() && !isToken) {
   config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
 }
 return config
}, error => {
   console.log(error)
   Promise.reject(error)
})

我们看到请求的地址是process.env.VUE_APP_BASE_API, 这是怎么访问到后端的的呢?我们回头看一下vue.config.js文件

devServer: {
    host: '0.0.0.0',
    port: port,
    open: true,
    proxy: {
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        target: `http://localhost:8080`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    },
    disableHostCheck: true
  },

这里做了一个代理,把process.env.VUE_APP_BASE_API地址映射成了http://localhost:8080。所以我们login最终访问后端的地址就变为http://localhost:8080/login。
现在看一下后端接收这个请求的代码。ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java。

 /**
  * 登录方法
  * 
  * @param loginBody 登录信息
  * @return 结果
  */
 @PostMapping("/login")
 public AjaxResult login(@RequestBody LoginBody loginBody)
 {
     AjaxResult ajax = AjaxResult.success();
     // 生成令牌
     String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
             loginBody.getUuid());
     ajax.put(Constants.TOKEN, token);
     return ajax;
 }

接收到/login的POST请求后,调用loginService.login方法进行验证,并生成token返回给客户端。接下来,看一下loginService.login方法。

/**
     * 登录验证
     * 
     * @param username 用户名
     * @param password 密码
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public String login(String username, String password, String code, String uuid)
    {
        ......
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(username, password));
        ......
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        return tokenService.createToken(loginUser);
    }

这里牵扯到Spring Security 的知识,我们看一下Spring Security的配置ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java。

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{ /**
     * 身份认证接口
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }
}

这里设置了userDetailService。UserDetailsServiceImpl实现了UserDetailService接口,实现了loadUserByUsername方法。我们再看一下UserDetailsServiceImpl.loadUserByUsername的实现:

@Service
public class UserDetailsServiceImpl implements UserDetailsService
{
@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
    {
        SysUser user = userService.selectUserByUserName(username);
        if (StringUtils.isNull(user))
        {
            log.info("登录用户:{} 不存在.", username);
            throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
        }
        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            log.info("登录用户:{} 已被删除.", username);
            throw new BaseException("对不起,您的账号:" + username + " 已被删除");
        }
        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            log.info("登录用户:{} 已被停用.", username);
            throw new BaseException("对不起,您的账号:" + username + " 已停用");
        }

        return createLoginUser(user);
    }
 }

就是根据用户名去数据库查询用户信息并返回。然后 再调用Spring Security内部的认证代码进行认证。

protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
       if (authentication.getCredentials() == null) {
           this.logger.debug("Authentication failed: no credentials provided");
           throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
       } else {
           String presentedPassword = authentication.getCredentials().toString();
           if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
               this.logger.debug("Authentication failed: password does not match stored value");
               throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
           }
       }
   }

就是比较根据用户名获取到的用户的密码和认证信息参数中的密码进行比较。更为详细的过程,这里引用了一位大神的文章,介绍的很详细。
https://blog.csdn.net/yuanlaijike/article/details/84703690
认证完成后,根据用户的信息,构建token,进行返回。前端收到返回后,存储token,并跳转网页。this.$router.push({ path: this.redirect || “/” });文章来源地址https://www.toymoban.com/news/detail-454126.html

到了这里,关于Ruoyi若依前后端分离框架【若依登录详细过程】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 若依RuoYi-Vue项目部署(前后端分离版本)

    RuoYi 是一个后台管理系统,基于经典技术组合(Spring Boot、Apache Shiro、MyBatis、Thymeleaf)主要目的让开发者注重专注业务,降低技术难度,从而节省人力成本,缩短项目周期,提高软件安全质量。 若依是作者给女儿取的名字(寓意:你若不离不弃,我必生死相依) 在线体验 若

    2023年04月08日
    浏览(36)
  • [ RuoYi ] 若依前后端分离 RuoYi-Vue 项目 war 包 Tomcat 项目部署

    Apache Tomcat® - Apache Tomcat 9 Software Downloads https://tomcat.apache.org/download-90.cgi Tomcat的主要特点和功能包括: ①Servlet和JSP容器:Tomcat作为一个Web服务器,可以解释执行Java Servlet和JSP代码,处理HTTP请求和响应,生成动态的Web页面。 ②独立性和易用性:Tomcat是一个独立的服务器,可以

    2024年02月07日
    浏览(46)
  • ruoyi若依前后端分离版部署centos7服务器(全)

    VMware虚拟机 centos7 安装环境如下 一、msql 5.7 二、nginx1.23.3 三、java8 四、redis 3.2.1 五、部署若依前端 六、部署若依后端 前言 虚拟机的桥接与nat模式 : 重点 重点!!! 无线不可以用桥接模式 ,而你用了nat模式会导致除了宿主机跟虚拟机外 同一个路由器下其他设备访问不到 !

    2024年02月02日
    浏览(48)
  • ruoyi-vue 新建模块--若依前后端分离系统代码生成。

    1. 在数据库中创建表 有几个要点: 1、必须要有自增主键; 2、必须要有表注释; 3、每个字段必须有注释; 》 2.使用代码生成功能,生成 基础代码 2.1 修改代码生成器中配置文件 generator.yml 修改完成后 → 需要重新启动右上角的RuoYiApplication 2.2 使用 系统工具 代码生成 创建菜

    2024年02月03日
    浏览(32)
  • 若依管理系统RuoYi-Vue(前后端分离版)项目启动教程

    RuoYi-Vue  是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring Security、MyBatis、Jwt、Vue),内置模块如:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理、代码生成等。在线定时任务配置;支持集群,支持多数据源,支持分布式事务

    2024年02月06日
    浏览(38)
  • 若依框架ruoyi-vue(前后端版)字典的使用

    显示效果:  状态实际 值为 1,讲师审核中为我们在字典管理中定义的。 步骤:先在ruoyi的字典管理中定义字典 字典管理中  然后根据字典设置自己需要的值 设置完值后,然后是前端表格的数据回显 这里先打开我们的前端vue工程,我们需要回显页面对应的vue文件中 在expor

    2024年02月11日
    浏览(36)
  • 若依(Ruoyi)前后端分离版项目部署到服务器(Linux环境)后,刷新页面报错:404 Not Found

    原文章: 若依(ruoyi)前后端分离版使用教程之若依后端部署阿里云服务器步骤(超详细)_蓝多多的小仓库的博客-CSDN博客 问题:         在若依项目部署服务器后,可以正常运行,但如果执行刷新页面操作,便会出现404 Not Found。 原因:         Nginx未正确配置。由

    2024年02月17日
    浏览(39)
  • ruoyi若依前后端分离项目部署到服务器后,PUT DELETE请求403错误,GET POST请求正常

    后端打包方式war,部署到tomcat8, PUT DELETE请求报403错误,网上有三种说法 第一种是跨域请求问题 第二种是服务器没有放开了PUT DELETE请求,需要前端添加header ruoyi vue 自动生成代码PUT DELETE为http不安全方法,这个怎么解决安全问题 · Issue #I43AX6 · 若依/RuoYi-Vue - Gitee.com 用域名访问

    2024年01月17日
    浏览(36)
  • 若依ruoyi前端vue使用jsencrypt.js加密后端java进行RSA解密(前后端交互RSA加解密)

    目录 1、前后端RSA加解密实现思路 2、前端 3、后端 按照约定来说公钥一般用来加密,大家都可以获取得到,私钥用来解密,当然你也可以混着用,以下示例是前端通过加密,后端解密.  -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ81AMIIBCgKCAQEA1+05vAf7m5NcLNLkRtsm gp+QdzcW6MVdayGTGBJG0v

    2024年02月06日
    浏览(44)
  • 【若依】框架:第01讲前后端分离项目

    介绍 | RuoYi         将下载好的若依项目导入IDEA,导入后配置MAVEN环境,等待下载完成。重点关注ruoyi-admin和ruoyi-system两个文件夹,前者放controller,后者放实体类、mapper、service ①打开文件夹选择若依前端项目(ruoyi-ui)文件夹 ②信任此作者进入 ③重点关心src文件夹下的api和

    2023年04月08日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包