瀏覽代碼

新增是否开启用户注册功能

RuoYi 3 年之前
父節點
當前提交
329aa68644
共有 33 個文件被更改,包括 594 次插入139 次删除
  1. 8 7
      ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteLogService.java
  2. 18 2
      ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java
  3. 1 1
      ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysLogininfor.java
  4. 3 2
      ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteLogFallbackFactory.java
  5. 8 1
      ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java
  6. 9 0
      ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java
  7. 11 0
      ruoyi-auth/src/main/java/com/ruoyi/auth/form/RegisterBody.java
  8. 75 11
      ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java
  9. 0 25
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
  10. 44 0
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/SecurityConstants.java
  11. 16 0
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java
  12. 6 6
      ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java
  13. 2 1
      ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/service/AsyncLogService.java
  14. 19 0
      ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/InnerAuth.java
  15. 51 0
      ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/InnerAuthAspect.java
  16. 8 8
      ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignRequestInterceptor.java
  17. 12 2
      ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java
  18. 1 0
      ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring.factories
  19. 11 3
      ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
  20. 3 3
      ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java
  21. 5 23
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysLogininforController.java
  22. 2 0
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysOperlogController.java
  23. 25 0
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
  24. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
  25. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
  26. 8 0
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
  27. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
  28. 11 0
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
  29. 12 0
      ruoyi-ui/src/api/login.js
  30. 5 0
      ruoyi-ui/src/router/index.js
  31. 9 3
      ruoyi-ui/src/views/login.vue
  32. 208 0
      ruoyi-ui/src/views/register.vue
  33. 0 38
      sql/ry_config_20210730.sql

+ 8 - 7
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteLogService.java

@@ -3,9 +3,11 @@ package com.ruoyi.system.api;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestHeader;
+import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.common.core.constant.ServiceNameConstants;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.api.domain.SysLogininfor;
 import com.ruoyi.system.api.domain.SysOperLog;
 import com.ruoyi.system.api.factory.RemoteLogFallbackFactory;
 
@@ -21,20 +23,19 @@ public interface RemoteLogService
      * 保存系统日志
      *
      * @param sysOperLog 日志实体
+     * @param source 请求来源
      * @return 结果
      */
     @PostMapping("/operlog")
-    R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog);
+    public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
 
     /**
      * 保存访问记录
      *
-     * @param username 用户名称
-     * @param status 状态
-     * @param message 消息
+     * @param sysLogininfor 访问实体
+     * @param source 请求来源
      * @return 结果
      */
     @PostMapping("/logininfor")
-    R<Boolean> saveLogininfor(@RequestParam("username") String username, @RequestParam("status") String status,
-            @RequestParam("message") String message);
+    public R<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
 }

+ 18 - 2
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java

@@ -3,8 +3,13 @@ package com.ruoyi.system.api;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.common.core.constant.ServiceNameConstants;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.api.domain.SysUser;
 import com.ruoyi.system.api.factory.RemoteUserFallbackFactory;
 import com.ruoyi.system.api.model.LoginUser;
 
@@ -20,8 +25,19 @@ public interface RemoteUserService
      * 通过用户名查询用户信息
      *
      * @param username 用户名
+     * @param source 请求来源
      * @return 结果
      */
-    @GetMapping(value = "/user/info/{username}")
-    public R<LoginUser> getUserInfo(@PathVariable("username") String username);
+    @GetMapping("/user/info/{username}")
+    public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
+
+    /**
+     * 注册用户信息
+     *
+     * @param sysUser 用户信息
+     * @param source 请求来源
+     * @return 结果
+     */
+    @PostMapping("/user/register")
+    public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
 }

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java → ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysLogininfor.java

@@ -1,4 +1,4 @@
-package com.ruoyi.system.domain;
+package com.ruoyi.system.api.domain;
 
 import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;

+ 3 - 2
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteLogFallbackFactory.java

@@ -6,6 +6,7 @@ import org.springframework.cloud.openfeign.FallbackFactory;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.system.api.RemoteLogService;
+import com.ruoyi.system.api.domain.SysLogininfor;
 import com.ruoyi.system.api.domain.SysOperLog;
 
 /**
@@ -25,13 +26,13 @@ public class RemoteLogFallbackFactory implements FallbackFactory<RemoteLogServic
         return new RemoteLogService()
         {
             @Override
-            public R<Boolean> saveLog(SysOperLog sysOperLog)
+            public R<Boolean> saveLog(SysOperLog sysOperLog, String source)
             {
                 return null;
             }
 
             @Override
-            public R<Boolean> saveLogininfor(String username, String status, String message)
+            public R<Boolean> saveLogininfor(SysLogininfor sysLogininfor, String source)
             {
                 return null;
             }

+ 8 - 1
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java

@@ -6,6 +6,7 @@ import org.springframework.cloud.openfeign.FallbackFactory;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.system.api.RemoteUserService;
+import com.ruoyi.system.api.domain.SysUser;
 import com.ruoyi.system.api.model.LoginUser;
 
 /**
@@ -25,10 +26,16 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
         return new RemoteUserService()
         {
             @Override
-            public R<LoginUser> getUserInfo(String username)
+            public R<LoginUser> getUserInfo(String username, String source)
             {
                 return R.fail("获取用户失败:" + throwable.getMessage());
             }
+
+            @Override
+            public R<Boolean> registerUserInfo(SysUser sysUser, String source)
+            {
+                return R.fail("注册用户失败:" + throwable.getMessage());
+            }
         };
     }
 }

+ 9 - 0
ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java

@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.auth.form.LoginBody;
+import com.ruoyi.auth.form.RegisterBody;
 import com.ruoyi.auth.service.SysLoginService;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.utils.StringUtils;
@@ -63,4 +64,12 @@ public class TokenController
         }
         return R.ok();
     }
+
+    @PostMapping("register")
+    public R<?> register(@RequestBody RegisterBody registerBody)
+    {
+        // 用户注册
+        sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
+        return R.ok();
+    }
 }

+ 11 - 0
ruoyi-auth/src/main/java/com/ruoyi/auth/form/RegisterBody.java

@@ -0,0 +1,11 @@
+package com.ruoyi.auth.form;
+
+/**
+ * 用户注册对象
+ * 
+ * @author ruoyi
+ */
+public class RegisterBody extends LoginBody
+{
+
+}

+ 75 - 11
ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java

@@ -3,14 +3,18 @@ package com.ruoyi.auth.service;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.common.core.constant.UserConstants;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.enums.UserStatus;
 import com.ruoyi.common.core.exception.BaseException;
 import com.ruoyi.common.core.utils.SecurityUtils;
+import com.ruoyi.common.core.utils.ServletUtils;
 import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.ip.IpUtils;
 import com.ruoyi.system.api.RemoteLogService;
 import com.ruoyi.system.api.RemoteUserService;
+import com.ruoyi.system.api.domain.SysLogininfor;
 import com.ruoyi.system.api.domain.SysUser;
 import com.ruoyi.system.api.model.LoginUser;
 
@@ -36,25 +40,25 @@ public class SysLoginService
         // 用户名或密码为空 错误
         if (StringUtils.isAnyBlank(username, password))
         {
-            remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
+            recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
             throw new BaseException("用户/密码必须填写");
         }
         // 密码如果不在指定范围内 错误
         if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                 || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
         {
-            remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
+            recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
             throw new BaseException("用户密码不在指定范围");
         }
         // 用户名不在指定范围内 错误
         if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                 || username.length() > UserConstants.USERNAME_MAX_LENGTH)
         {
-            remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
+            recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
             throw new BaseException("用户名不在指定范围");
         }
         // 查询用户信息
-        R<LoginUser> userResult = remoteUserService.getUserInfo(username);
+        R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
 
         if (R.FAIL == userResult.getCode())
         {
@@ -63,33 +67,93 @@ public class SysLoginService
 
         if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
         {
-            remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
+            recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
             throw new BaseException("登录用户:" + username + " 不存在");
         }
         LoginUser userInfo = userResult.getData();
         SysUser user = userResult.getData().getSysUser();
         if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
         {
-            remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
-
+            recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
             throw new BaseException("对不起,您的账号:" + username + " 已被删除");
         }
         if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
         {
-            remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
+            recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
             throw new BaseException("对不起,您的账号:" + username + " 已停用");
         }
         if (!SecurityUtils.matchesPassword(password, user.getPassword()))
         {
-            remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误");
+            recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误");
             throw new BaseException("用户不存在/密码错误");
         }
-        remoteLogService.saveLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
+        recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
         return userInfo;
     }
 
     public void logout(String loginName)
     {
-        remoteLogService.saveLogininfor(loginName, Constants.LOGOUT, "退出成功");
+        recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
+    }
+
+    /**
+     * 注册
+     */
+    public void register(String username, String password)
+    {
+        // 用户名或密码为空 错误
+        if (StringUtils.isAnyBlank(username, password))
+        {
+            throw new BaseException("用户/密码必须填写");
+        }
+        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
+        {
+            throw new BaseException("账户长度必须在2到20个字符之间");
+        }
+        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
+        {
+            throw new BaseException("密码长度必须在5到20个字符之间");
+        }
+
+        // 注册用户信息
+        SysUser sysUser = new SysUser();
+        sysUser.setUserName(username);
+        sysUser.setNickName(username);
+        sysUser.setPassword(SecurityUtils.encryptPassword(password));
+        R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
+
+        if (R.FAIL == registerResult.getCode())
+        {
+            throw new BaseException(registerResult.getMsg());
+        }
+        recordLogininfor(username, Constants.REGISTER, "注册成功");
+    }
+
+    /**
+     * 记录登录信息
+     * 
+     * @param username 用户名
+     * @param status 状态
+     * @param message 消息内容
+     * @return
+     */
+    public void recordLogininfor(String username, String status, String message)
+    {
+        SysLogininfor logininfor = new SysLogininfor();
+        logininfor.setUserName(username);
+        logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
+        logininfor.setMsg(message);
+        // 日志状态
+        if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
+        {
+            logininfor.setStatus("0");
+        }
+        else if (Constants.LOGIN_FAIL.equals(status))
+        {
+            logininfor.setStatus("1");
+        }
+        remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
     }
 }

+ 0 - 25
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java

@@ -7,33 +7,8 @@ package com.ruoyi.common.core.constant;
  */
 public class CacheConstants
 {
-    /**
-     * 令牌自定义标识
-     */
-    public static final String TOKEN_AUTHENTICATION = "Authorization";
-
-    /**
-     * 令牌前缀
-     */
-    public static final String TOKEN_PREFIX = "Bearer ";
-
     /**
      * 权限缓存前缀
      */
     public final static String LOGIN_TOKEN_KEY = "login_tokens:";
-
-    /**
-     * 用户ID字段
-     */
-    public static final String DETAILS_USER_ID = "user_id";
-
-    /**
-     * 用户名字段
-     */
-    public static final String DETAILS_USERNAME = "username";
-
-    /**
-     * 授权信息字段
-     */
-    public static final String AUTHORIZATION_HEADER = "authorization";
 }

+ 44 - 0
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/SecurityConstants.java

@@ -0,0 +1,44 @@
+package com.ruoyi.common.core.constant;
+
+/**
+ * 权限相关通用常量
+ * 
+ * @author ruoyi
+ */
+public class SecurityConstants
+{
+    /**
+     * 令牌自定义标识
+     */
+    public static final String TOKEN_AUTHENTICATION = "Authorization";
+
+    /**
+     * 令牌前缀
+     */
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    /**
+     * 用户ID字段
+     */
+    public static final String DETAILS_USER_ID = "user_id";
+
+    /**
+     * 用户名字段
+     */
+    public static final String DETAILS_USERNAME = "username";
+
+    /**
+     * 授权信息字段
+     */
+    public static final String AUTHORIZATION_HEADER = "authorization";
+
+    /**
+     * 请求来源
+     */
+    public static final String FROM_SOURCE = "from-source";
+
+    /**
+     * 内部请求
+     */
+    public static final String INNER = "inner";
+}

+ 16 - 0
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/exception/InnerAuthException.java

@@ -0,0 +1,16 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 内部认证异常
+ * 
+ * @author ruoyi
+ */
+public class InnerAuthException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    public InnerAuthException(String message)
+    {
+        super(message);
+    }
+}

+ 6 - 6
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java

@@ -2,7 +2,7 @@ package com.ruoyi.common.core.utils;
 
 import javax.servlet.http.HttpServletRequest;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.common.core.text.Convert;
 
 /**
@@ -17,7 +17,7 @@ public class SecurityUtils
      */
     public static String getUsername()
     {
-        String username = ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USERNAME);
+        String username = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USERNAME);
         return ServletUtils.urlDecode(username);
     }
 
@@ -26,7 +26,7 @@ public class SecurityUtils
      */
     public static Long getUserId()
     {
-        return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USER_ID));
+        return Convert.toLong(ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USER_ID));
     }
 
     /**
@@ -42,7 +42,7 @@ public class SecurityUtils
      */
     public static String getToken(HttpServletRequest request)
     {
-        String token = request.getHeader(CacheConstants.TOKEN_AUTHENTICATION);
+        String token = request.getHeader(SecurityConstants.TOKEN_AUTHENTICATION);
         return replaceTokenPrefix(token);
     }
 
@@ -51,9 +51,9 @@ public class SecurityUtils
      */
     public static String replaceTokenPrefix(String token)
     {
-        if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
+        if (StringUtils.isNotEmpty(token) && token.startsWith(SecurityConstants.TOKEN_PREFIX))
         {
-            token = token.replace(CacheConstants.TOKEN_PREFIX, "");
+            token = token.replace(SecurityConstants.TOKEN_PREFIX, "");
         }
         return token;
     }

+ 2 - 1
ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/service/AsyncLogService.java

@@ -3,6 +3,7 @@ package com.ruoyi.common.log.service;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.system.api.RemoteLogService;
 import com.ruoyi.system.api.domain.SysOperLog;
 
@@ -23,6 +24,6 @@ public class AsyncLogService
     @Async
     public void saveSysLog(SysOperLog sysOperLog)
     {
-        remoteLogService.saveLog(sysOperLog);
+        remoteLogService.saveLog(sysOperLog, SecurityConstants.INNER);
     }
 }

+ 19 - 0
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/InnerAuth.java

@@ -0,0 +1,19 @@
+package com.ruoyi.common.security.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 内部认证注解
+ * 
+ * @author ruoyi
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface InnerAuth
+{
+    /**
+     * 是否校验用户信息
+     */
+    boolean isUser() default false;
+}

+ 51 - 0
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/InnerAuthAspect.java

@@ -0,0 +1,51 @@
+package com.ruoyi.common.security.aspect;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.core.Ordered;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.core.constant.SecurityConstants;
+import com.ruoyi.common.core.exception.InnerAuthException;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.security.annotation.InnerAuth;
+
+/**
+ * 内部服务调用验证处理
+ * 
+ * @author ruoyi
+ */
+@Aspect
+@Component
+public class InnerAuthAspect implements Ordered
+{
+    @Around("@annotation(innerAuth)")
+    public Object innerAround(ProceedingJoinPoint point, InnerAuth innerAuth) throws Throwable
+    {
+        String source = ServletUtils.getRequest().getHeader(SecurityConstants.FROM_SOURCE);
+        // 内部请求验证
+        if (!StringUtils.equals(SecurityConstants.INNER, source))
+        {
+            throw new InnerAuthException("没有内部访问权限,不允许访问");
+        }
+
+        String userid = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USER_ID);
+        String username = ServletUtils.getRequest().getHeader(SecurityConstants.DETAILS_USERNAME);
+        // 用户信息验证
+        if (innerAuth.isUser() && (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username)))
+        {
+            throw new InnerAuthException("没有设置用户信息,不允许访问 ");
+        }
+        return point.proceed();
+    }
+
+    /**
+     * 确保在权限认证aop执行前执行
+     */
+    @Override
+    public int getOrder()
+    {
+        return Ordered.HIGHEST_PRECEDENCE + 1;
+    }
+}

+ 8 - 8
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignRequestInterceptor.java

@@ -2,11 +2,11 @@ package com.ruoyi.common.security.feign;
 
 import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
-import com.ruoyi.common.core.utils.ip.IpUtils;
 import org.springframework.stereotype.Component;
-import com.ruoyi.common.core.constant.CacheConstants;
+import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.common.core.utils.ServletUtils;
 import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.ip.IpUtils;
 import feign.RequestInterceptor;
 import feign.RequestTemplate;
 
@@ -26,20 +26,20 @@ public class FeignRequestInterceptor implements RequestInterceptor
         {
             Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);
             // 传递用户信息请求头,防止丢失
-            String userId = headers.get(CacheConstants.DETAILS_USER_ID);
+            String userId = headers.get(SecurityConstants.DETAILS_USER_ID);
             if (StringUtils.isNotEmpty(userId))
             {
-                requestTemplate.header(CacheConstants.DETAILS_USER_ID, userId);
+                requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId);
             }
-            String userName = headers.get(CacheConstants.DETAILS_USERNAME);
+            String userName = headers.get(SecurityConstants.DETAILS_USERNAME);
             if (StringUtils.isNotEmpty(userName))
             {
-                requestTemplate.header(CacheConstants.DETAILS_USERNAME, userName);
+                requestTemplate.header(SecurityConstants.DETAILS_USERNAME, userName);
             }
-            String authentication = headers.get(CacheConstants.AUTHORIZATION_HEADER);
+            String authentication = headers.get(SecurityConstants.AUTHORIZATION_HEADER);
             if (StringUtils.isNotEmpty(authentication))
             {
-                requestTemplate.header(CacheConstants.AUTHORIZATION_HEADER, authentication);
+                requestTemplate.header(SecurityConstants.AUTHORIZATION_HEADER, authentication);
             }
 
             // 配置客户端IP

+ 12 - 2
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/GlobalExceptionHandler.java

@@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
 import com.ruoyi.common.core.exception.BaseException;
 import com.ruoyi.common.core.exception.CustomException;
 import com.ruoyi.common.core.exception.DemoModeException;
+import com.ruoyi.common.core.exception.InnerAuthException;
 import com.ruoyi.common.core.exception.PreAuthorizeException;
 import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.common.core.web.domain.AjaxResult;
@@ -73,7 +74,7 @@ public class GlobalExceptionHandler
         String message = e.getBindingResult().getFieldError().getDefaultMessage();
         return AjaxResult.error(message);
     }
-    
+
     /**
      * 权限异常
      */
@@ -82,7 +83,16 @@ public class GlobalExceptionHandler
     {
         return AjaxResult.error("没有权限,请联系管理员授权");
     }
-    
+
+    /**
+     * 内部认证异常
+     */
+    @ExceptionHandler(InnerAuthException.class)
+    public AjaxResult InnerAuthException(InnerAuthException e)
+    {
+        return AjaxResult.error(e.getMessage());
+    }
+
     /**
      * 演示模式异常
      */

+ 1 - 0
ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring.factories

@@ -1,4 +1,5 @@
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
   com.ruoyi.common.security.service.TokenService,\
   com.ruoyi.common.security.aspect.PreAuthorizeAspect,\
+  com.ruoyi.common.security.aspect.InnerAuthAspect,\
   com.ruoyi.common.security.handler.GlobalExceptionHandler

+ 11 - 3
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java

@@ -15,6 +15,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.common.core.constant.CacheConstants;
 import com.ruoyi.common.core.constant.Constants;
 import com.ruoyi.common.core.constant.HttpStatus;
+import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.common.core.utils.SecurityUtils;
 import com.ruoyi.common.core.utils.ServletUtils;
 import com.ruoyi.common.core.utils.StringUtils;
@@ -77,8 +78,10 @@ public class AuthFilter implements GlobalFilter, Ordered
         // 设置过期时间
         redisService.expire(getTokenKey(token), EXPIRE_TIME);
         // 设置用户信息到请求
-        addHeader(mutate, CacheConstants.DETAILS_USER_ID, userid);
-        addHeader(mutate, CacheConstants.DETAILS_USERNAME, username);
+        addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);
+        addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username);
+        // 内部请求来源参数清除
+        removeHeader(mutate, SecurityConstants.FROM_SOURCE);
         return chain.filter(exchange.mutate().request(mutate.build()).build());
     }
 
@@ -93,6 +96,11 @@ public class AuthFilter implements GlobalFilter, Ordered
         mutate.header(name, valueEncode);
     }
 
+    private void removeHeader(ServerHttpRequest.Builder mutate, String name)
+    {
+        mutate.headers(httpHeaders -> httpHeaders.remove(name)).build();
+    }
+
     private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg)
     {
         log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
@@ -112,7 +120,7 @@ public class AuthFilter implements GlobalFilter, Ordered
      */
     private String getToken(ServerHttpRequest request)
     {
-        String token = request.getHeaders().getFirst(CacheConstants.TOKEN_AUTHENTICATION);
+        String token = request.getHeaders().getFirst(SecurityConstants.TOKEN_AUTHENTICATION);
         return SecurityUtils.replaceTokenPrefix(token);
     }
 

+ 3 - 3
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java

@@ -25,7 +25,7 @@ import reactor.core.publisher.Flux;
 @Component
 public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object>
 {
-    private final static String AUTH_URL = "/auth/login";
+    private final static String[] VALIDATE_URL = new String[] { "/auth/login", "/auth/register" };
 
     @Autowired
     private ValidateCodeService validateCodeService;
@@ -43,8 +43,8 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object>
         return (exchange, chain) -> {
             ServerHttpRequest request = exchange.getRequest();
 
-            // 非登录请求或验证码关闭,不处理
-            if (!StringUtils.containsIgnoreCase(request.getURI().getPath(), AUTH_URL) || !captchaProperties.getEnabled())
+            // 非登录/注册请求或验证码关闭,不处理
+            if (!StringUtils.containsAnyIgnoreCase(request.getURI().getPath(), VALIDATE_URL) || !captchaProperties.getEnabled())
             {
                 return chain.filter(exchange);
             }

+ 5 - 23
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysLogininforController.java

@@ -8,20 +8,18 @@ import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
-import com.ruoyi.common.core.constant.Constants;
-import com.ruoyi.common.core.utils.ServletUtils;
-import com.ruoyi.common.core.utils.ip.IpUtils;
 import com.ruoyi.common.core.utils.poi.ExcelUtil;
 import com.ruoyi.common.core.web.controller.BaseController;
 import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.core.web.page.TableDataInfo;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.security.annotation.InnerAuth;
 import com.ruoyi.common.security.annotation.PreAuthorize;
-import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.api.domain.SysLogininfor;
 import com.ruoyi.system.service.ISysLogininforService;
 
 /**
@@ -72,26 +70,10 @@ public class SysLogininforController extends BaseController
         return AjaxResult.success();
     }
 
+    @InnerAuth
     @PostMapping
-    public AjaxResult add(@RequestParam("username") String username, @RequestParam("status") String status,
-            @RequestParam("message") String message)
+    public AjaxResult add(@RequestBody SysLogininfor logininfor)
     {
-        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
-
-        // 封装对象
-        SysLogininfor logininfor = new SysLogininfor();
-        logininfor.setUserName(username);
-        logininfor.setIpaddr(ip);
-        logininfor.setMsg(message);
-        // 日志状态
-        if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
-        {
-            logininfor.setStatus("0");
-        }
-        else if (Constants.LOGIN_FAIL.equals(status))
-        {
-            logininfor.setStatus("1");
-        }
         return toAjax(logininforService.insertLogininfor(logininfor));
     }
 }

+ 2 - 0
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysOperlogController.java

@@ -17,6 +17,7 @@ import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.core.web.page.TableDataInfo;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.security.annotation.InnerAuth;
 import com.ruoyi.common.security.annotation.PreAuthorize;
 import com.ruoyi.system.api.domain.SysOperLog;
 import com.ruoyi.system.service.ISysOperLogService;
@@ -69,6 +70,7 @@ public class SysOperlogController extends BaseController
         return AjaxResult.success();
     }
 
+    @InnerAuth
     @PostMapping
     public AjaxResult add(@RequestBody SysOperLog operLog)
     {

+ 25 - 0
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java

@@ -27,10 +27,12 @@ import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.core.web.page.TableDataInfo;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.security.annotation.InnerAuth;
 import com.ruoyi.common.security.annotation.PreAuthorize;
 import com.ruoyi.system.api.domain.SysRole;
 import com.ruoyi.system.api.domain.SysUser;
 import com.ruoyi.system.api.model.LoginUser;
+import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysPermissionService;
 import com.ruoyi.system.service.ISysPostService;
 import com.ruoyi.system.service.ISysRoleService;
@@ -57,6 +59,9 @@ public class SysUserController extends BaseController
     @Autowired
     private ISysPermissionService permissionService;
 
+    @Autowired
+    private ISysConfigService configService;
+
     /**
      * 获取用户列表
      */
@@ -101,6 +106,7 @@ public class SysUserController extends BaseController
     /**
      * 获取当前用户信息
      */
+    @InnerAuth
     @GetMapping("/info/{username}")
     public R<LoginUser> info(@PathVariable("username") String username)
     {
@@ -120,6 +126,25 @@ public class SysUserController extends BaseController
         return R.ok(sysUserVo);
     }
 
+    /**
+     * 注册用户信息
+     */
+    @InnerAuth
+    @PostMapping("/register")
+    public R<Boolean> register(@RequestBody SysUser sysUser)
+    {
+        String username = sysUser.getUserName();
+        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
+        {
+            return R.fail("当前系统没有开启注册功能!");
+        }
+        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username)))
+        {
+            return R.fail("保存用户'" + username + "'失败,注册账号已存在");
+        }
+        return R.ok(userService.registerUser(sysUser));
+    }
+
     /**
      * 获取用户信息
      * 

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java

@@ -1,7 +1,7 @@
 package com.ruoyi.system.mapper;
 
 import java.util.List;
-import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.api.domain.SysLogininfor;
 
 /**
  * 系统访问日志情况信息 数据层

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java

@@ -1,7 +1,7 @@
 package com.ruoyi.system.service;
 
 import java.util.List;
-import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.api.domain.SysLogininfor;
 
 /**
  * 系统访问日志情况信息 服务层

+ 8 - 0
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java

@@ -105,6 +105,14 @@ public interface ISysUserService
      */
     public int insertUser(SysUser user);
 
+    /**
+     * 注册用户信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    public boolean registerUser(SysUser user);
+
     /**
      * 修改用户信息
      * 

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java

@@ -3,7 +3,7 @@ package com.ruoyi.system.service.impl;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.api.domain.SysLogininfor;
 import com.ruoyi.system.mapper.SysLogininforMapper;
 import com.ruoyi.system.service.ISysLogininforService;
 

+ 11 - 0
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

@@ -246,6 +246,17 @@ public class SysUserServiceImpl implements ISysUserService
         return rows;
     }
 
+    /**
+     * 注册用户信息
+     * 
+     * @param user 用户信息
+     * @return 结果
+     */
+    public boolean registerUser(SysUser user)
+    {
+        return userMapper.insertUser(user) > 0;
+    }
+
     /**
      * 修改保存用户信息
      * 

+ 12 - 0
ruoyi-ui/src/api/login.js

@@ -9,6 +9,18 @@ export function login(username, password, code, uuid) {
   })
 }
 
+// 注册方法
+export function register(data) {
+  return request({
+    url: '/auth/register',
+    headers: {
+      isToken: false
+    },
+    method: 'post',
+    data: data
+  })
+}
+
 // 刷新方法
 export function refreshToken() {
   return request({

+ 5 - 0
ruoyi-ui/src/router/index.js

@@ -43,6 +43,11 @@ export const constantRoutes = [
     component: (resolve) => require(['@/views/login'], resolve),
     hidden: true
   },
+  {
+    path: '/register',
+    component: (resolve) => require(['@/views/register'], resolve),
+    hidden: true
+  },
   {
     path: '/404',
     component: (resolve) => require(['@/views/error/404'], resolve),

+ 9 - 3
ruoyi-ui/src/views/login.vue

@@ -44,6 +44,9 @@
           <span v-if="!loading">登 录</span>
           <span v-else>登 录 中...</span>
         </el-button>
+        <div style="float: right;" v-if="register">
+          <router-link class="link-type" :to="'/register'">立即注册</router-link>
+        </div>
       </el-form-item>
     </el-form>
     <!--  底部  -->
@@ -73,15 +76,18 @@ export default {
       },
       loginRules: {
         username: [
-          { required: true, trigger: "blur", message: "用户名不能为空" }
+          { required: true, trigger: "blur", message: "请输入您的账号" }
         ],
         password: [
-          { required: true, trigger: "blur", message: "密码不能为空" }
+          { required: true, trigger: "blur", message: "请输入您的密码" }
         ],
-        code: [{ required: true, trigger: "change", message: "验证码不能为空" }]
+        code: [{ required: true, trigger: "change", message: "请输入验证码" }]
       },
       loading: false,
+      // 验证码开关
       captchaOnOff: true,
+      // 注册开关
+      register: false,
       redirect: undefined
     };
   },

+ 208 - 0
ruoyi-ui/src/views/register.vue

@@ -0,0 +1,208 @@
+<template>
+  <div class="register">
+    <el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
+      <h3 class="title">若依后台管理系统</h3>
+      <el-form-item prop="username">
+        <el-input v-model="registerForm.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="registerForm.password"
+          type="password"
+          auto-complete="off"
+          placeholder="密码"
+          @keyup.enter.native="handleRegister"
+        >
+          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
+        </el-input>
+      </el-form-item>
+      <el-form-item prop="confirmPassword">
+        <el-input
+          v-model="registerForm.confirmPassword"
+          type="password"
+          auto-complete="off"
+          placeholder="确认密码"
+          @keyup.enter.native="handleRegister"
+        >
+          <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
+        </el-input>
+      </el-form-item>
+      <el-form-item prop="code" v-if="captchaOnOff">
+        <el-input
+          v-model="registerForm.code"
+          auto-complete="off"
+          placeholder="验证码"
+          style="width: 63%"
+          @keyup.enter.native="handleRegister"
+        >
+          <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
+        </el-input>
+        <div class="register-code">
+          <img :src="codeUrl" @click="getCode" class="register-code-img"/>
+        </div>
+      </el-form-item>
+      <el-form-item style="width:100%;">
+        <el-button
+          :loading="loading"
+          size="medium"
+          type="primary"
+          style="width:100%;"
+          @click.native.prevent="handleRegister"
+        >
+          <span v-if="!loading">注 册</span>
+          <span v-else>注 册 中...</span>
+        </el-button>
+        <div style="float: right;">
+          <router-link class="link-type" :to="'/login'">使用已有账户登录</router-link>
+        </div>
+      </el-form-item>
+    </el-form>
+    <!--  底部  -->
+    <div class="el-register-footer">
+      <span>Copyright © 2018-2021 ruoyi.vip All Rights Reserved.</span>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getCodeImg, register } from "@/api/login";
+
+export default {
+  name: "Register",
+  data() {
+    const equalToPassword = (rule, value, callback) => {
+      if (this.registerForm.password !== value) {
+        callback(new Error("两次输入的密码不一致"));
+      } else {
+        callback();
+      }
+    };
+    return {
+      codeUrl: "",
+      registerForm: {
+        username: "",
+        password: "",
+        confirmPassword: "",
+        code: "",
+        uuid: ""
+      },
+      registerRules: {
+        username: [
+          { required: true, trigger: "blur", message: "请输入您的账号" },
+          { min: 2, max: 20, message: '用户账号长度必须介于 2 和 20 之间', trigger: 'blur' }
+        ],
+        password: [
+          { required: true, trigger: "blur", message: "请输入您的密码" },
+          { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' }
+        ],
+        confirmPassword: [
+          { required: true, trigger: "blur", message: "请再次输入您的密码" },
+          { required: true, validator: equalToPassword, trigger: "blur" }
+        ],
+        code: [{ required: true, trigger: "change", message: "请输入验证码" }]
+      },
+      loading: false,
+      captchaOnOff: true
+    };
+  },
+  created() {
+    this.getCode();
+  },
+  methods: {
+    getCode() {
+      getCodeImg().then(res => {
+        this.captchaOnOff = res.captchaOnOff === undefined ? true : res.captchaOnOff;
+        if (this.captchaOnOff) {
+          this.codeUrl = "data:image/gif;base64," + res.img;
+          this.registerForm.uuid = res.uuid;
+        }
+      });
+    },
+    handleRegister() {
+      this.$refs.registerForm.validate(valid => {
+        if (valid) {
+          this.loading = true;
+          register(this.registerForm).then(res => {
+            const username = this.registerForm.username;
+            this.$alert("<font color='red'>恭喜你,您的账号 " + username + " 注册成功!</font>", '系统提示', {
+              dangerouslyUseHTMLString: true
+            }).then(() => {
+              this.$router.push("/login");
+            }).catch(() => {});
+          }).catch(() => {
+            this.loading = false;
+            if (this.captchaOnOff) {
+              this.getCode();
+            }
+          })
+        }
+      });
+    }
+  }
+};
+</script>
+
+<style rel="stylesheet/scss" lang="scss">
+.register {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  background-image: url("../assets/images/login-background.jpg");
+  background-size: cover;
+}
+.title {
+  margin: 0px auto 30px auto;
+  text-align: center;
+  color: #707070;
+}
+
+.register-form {
+  border-radius: 6px;
+  background: #ffffff;
+  width: 400px;
+  padding: 25px 25px 5px 25px;
+  .el-input {
+    height: 38px;
+    input {
+      height: 38px;
+    }
+  }
+  .input-icon {
+    height: 39px;
+    width: 14px;
+    margin-left: 2px;
+  }
+}
+.register-tip {
+  font-size: 13px;
+  text-align: center;
+  color: #bfbfbf;
+}
+.register-code {
+  width: 33%;
+  height: 38px;
+  float: right;
+  img {
+    cursor: pointer;
+    vertical-align: middle;
+  }
+}
+.el-register-footer {
+  height: 40px;
+  line-height: 40px;
+  position: fixed;
+  bottom: 0;
+  width: 100%;
+  text-align: center;
+  color: #fff;
+  font-family: Arial;
+  font-size: 12px;
+  letter-spacing: 1px;
+}
+.register-code-img {
+  height: 38px;
+}
+</style>

文件差異過大導致無法顯示
+ 0 - 38
sql/ry_config_20210730.sql


部分文件因文件數量過多而無法顯示