Przeglądaj źródła

增加登录日志保存。解决注销获取不到用户信息

xusl 2 lat temu
rodzic
commit
d647358c31
27 zmienionych plików z 985 dodań i 126 usunięć
  1. 6 0
      backend/pom.xml
  2. 10 9
      backend/src/main/java/com/jiayue/ssi/config/WebSecurityConfig.java
  3. 31 9
      backend/src/main/java/com/jiayue/ssi/controller/SysRoleController.java
  4. 133 0
      backend/src/main/java/com/jiayue/ssi/entity/SysLogininfor.java
  5. 71 0
      backend/src/main/java/com/jiayue/ssi/factory/LoginFactory.java
  6. 10 0
      backend/src/main/java/com/jiayue/ssi/filter/MailCodeFilter.java
  7. 11 0
      backend/src/main/java/com/jiayue/ssi/filter/VerifyCodeFilter.java
  8. 18 0
      backend/src/main/java/com/jiayue/ssi/filter/VerifySmFilter.java
  9. 4 0
      backend/src/main/java/com/jiayue/ssi/handler/CustomAuthenticationFailureHandler.java
  10. 6 0
      backend/src/main/java/com/jiayue/ssi/handler/CustomAuthenticationSuccessHandler.java
  11. 51 0
      backend/src/main/java/com/jiayue/ssi/handler/CustomLogoutSuccessHandler.java
  12. 48 0
      backend/src/main/java/com/jiayue/ssi/mapper/SysLogininforMapper.java
  13. 0 2
      backend/src/main/java/com/jiayue/ssi/mapper/SysMenuMapper.java
  14. 0 2
      backend/src/main/java/com/jiayue/ssi/mapper/SysParameterMapper.java
  15. 7 7
      backend/src/main/java/com/jiayue/ssi/mapper/SysRoleMapper.java
  16. 0 2
      backend/src/main/java/com/jiayue/ssi/mapper/SysUserMapper.java
  17. 42 0
      backend/src/main/java/com/jiayue/ssi/service/SysLogininforService.java
  18. 8 15
      backend/src/main/java/com/jiayue/ssi/service/SysRoleService.java
  19. 21 0
      backend/src/main/java/com/jiayue/ssi/service/impl/SysLogininforServiceImpl.java
  20. 26 56
      backend/src/main/java/com/jiayue/ssi/service/impl/SysRoleServiceImpl.java
  21. 50 0
      backend/src/main/java/com/jiayue/ssi/util/AddressUtils.java
  22. 219 0
      backend/src/main/java/com/jiayue/ssi/util/ServletUtils.java
  23. 157 0
      backend/src/main/java/com/jiayue/ssi/util/SpringUtils.java
  24. 2 9
      backend/src/main/resources/mapper/system/SysRoleMapper.xml
  25. 9 3
      ui/src/layout/components/Navbar.vue
  26. 1 0
      ui/src/views/login/index.vue
  27. 44 12
      ui/src/views/sysManager/roleManager/index.vue

+ 6 - 0
backend/pom.xml

@@ -208,6 +208,12 @@
             <artifactId>jna-platform</artifactId>
             <version>5.5.0</version>
         </dependency>
+        <!-- 解析客户端操作系统、浏览器等 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>1.21</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

+ 10 - 9
backend/src/main/java/com/jiayue/ssi/config/WebSecurityConfig.java

@@ -1,10 +1,7 @@
 package com.jiayue.ssi.config;
 
 import com.jiayue.ssi.filter.*;
-import com.jiayue.ssi.handler.CustomAuthenticationFailureHandler;
-import com.jiayue.ssi.handler.CustomAuthenticationSuccessHandler;
-import com.jiayue.ssi.handler.EntryPointUnauthorizedHandler;
-import com.jiayue.ssi.handler.RestAccessDeniedHandler;
+import com.jiayue.ssi.handler.*;
 import com.jiayue.ssi.service.impl.UserServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
@@ -20,6 +17,8 @@ import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.web.filter.CorsFilter;
 
 
 /**
@@ -42,7 +41,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
     @Autowired
     RestAccessDeniedHandler restAccessDeniedHandler;
     @Autowired
-    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
+    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
+    @Autowired
+    CustomLogoutSuccessHandler customLogoutSuccessHandler;
+
 
     @Bean
     public MyAuthenticationProvider eacpsAuthenticationProvider(){
@@ -65,10 +67,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
     @Override
     protected void configure(HttpSecurity httpSecurity) throws Exception {
         httpSecurity.addFilterBefore(new InterfaceLimitFilter(), UsernamePasswordAuthenticationFilter.class);
-        httpSecurity.addFilterBefore(new VerifySmFilter(), UsernamePasswordAuthenticationFilter.class);
+        httpSecurity.addFilterBefore(new VerifySmFilter(), LogoutFilter.class);
         httpSecurity.addFilterBefore(new VerifyCodeFilter(), UsernamePasswordAuthenticationFilter.class);
         httpSecurity.addFilterBefore(new MailCodeFilter(), UsernamePasswordAuthenticationFilter.class);
-        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
+        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, LogoutFilter.class);
         httpSecurity
                 // 由于使用的是JWT,我们这里不需要csrf
                 .csrf().disable()
@@ -84,9 +86,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
         httpSecurity.formLogin().loginProcessingUrl("/user/login")
                 .successHandler(customAuthenticationSuccessHandler)
                 .failureHandler(customAuthenticationFailureHandler);
+        httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(customLogoutSuccessHandler);
         httpSecurity.exceptionHandling().authenticationEntryPoint(entryPointUnauthorizedHandler).accessDeniedHandler(restAccessDeniedHandler);
-
-
     }
 
     //针对静态资源放行

+ 31 - 9
backend/src/main/java/com/jiayue/ssi/controller/SysRoleController.java

@@ -46,7 +46,6 @@ public class SysRoleController {
 //    private ISysDeptService deptService;
 
 
-
     /**
      * 获取参数分页信息
      *
@@ -55,7 +54,7 @@ public class SysRoleController {
     //    @PreAuthorize("@ss.hasPermi('system:role:list')")
     @GetMapping(value = "/getAll")
     @InterfaceLimit
-    public ResponseVO getAll(Integer currentPage, Integer pageSize,String roleName,String status, String roleKey) {
+    public ResponseVO getAll(Integer currentPage, Integer pageSize, String roleName, String status, String roleKey) {
         try {
             QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
             if (StringUtils.isNotEmpty(roleName)) {
@@ -89,7 +88,7 @@ public class SysRoleController {
             ///////加校验/////
             role.setCreateBy(SecurityContextUtil.getSysUser().getUsername());
             int i = roleService.insertRole(role);
-            if (i>0) {
+            if (i > 0) {
                 return ResponseVO.success("添加角色成功");
             } else {
                 log.error("添加角色失败");
@@ -116,15 +115,15 @@ public class SysRoleController {
         }
 ///////加校验/////
         try {
-            if (roleService.updateRole(role)>0) {
-                return ResponseVO.success("修改用户信息成功");
+            if (roleService.updateRole(role) > 0) {
+                return ResponseVO.success("修改角色信息成功");
             } else {
                 log.error("修改用户信息失败");
-                return ResponseVO.fail("修改用户信息失败");
+                return ResponseVO.fail("修改角色信息失败");
             }
         } catch (Exception e) {
             e.printStackTrace();
-            log.error("修改用户信息异常");
+            log.error("修改角色信息异常");
             return ResponseVO.error(e);
         }
     }
@@ -133,11 +132,34 @@ public class SysRoleController {
      * 根据角色编号获取详细信息
      */
     @GetMapping(value = "getInfo")
-    public ResponseVO getInfo(Long roleId)
-    {
+    public ResponseVO getInfo(Long roleId) {
         return ResponseVO.success(roleService.selectRoleById(roleId));
     }
 
+    /**
+     * 删除角色
+     */
+    @PostMapping(value = "/delRole")
+    @InterfaceLimit
+    public ResponseVO delRole(String roleId) {
+        if (StringUtils.isEmpty(roleId)) {
+            return ResponseVO.fail("id不能为空!");
+        }
+        try {
+            int bo = roleService.deleteRoleById(Long.parseLong(roleId));
+            if (bo > 0) {
+                return ResponseVO.success("删除角色信息成功");
+            } else {
+                log.error("删除用户信息失败");
+                return ResponseVO.fail("删除角色信息失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("删除角色信息异常");
+            return ResponseVO.error(e);
+        }
+    }
+
 //    @Log(title = "角色管理", businessType = BusinessType.EXPORT)
 //    @PreAuthorize("@ss.hasPermi('system:role:export')")
 //    @PostMapping("/export")

+ 133 - 0
backend/src/main/java/com/jiayue/ssi/entity/SysLogininfor.java

@@ -0,0 +1,133 @@
+package com.jiayue.ssi.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.util.Date;
+
+/**
+ * 系统访问记录表 sys_logininfor
+ *
+ * @author ruoyi
+ */
+public class SysLogininfor extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    private Long infoId;
+
+    /** 用户账号 */
+    private String userName;
+
+    /** 登录状态 0成功 1失败 */
+    private String status;
+
+    /** 登录IP地址 */
+    private String ipaddr;
+
+    /** 登录地点 */
+    private String loginLocation;
+
+    /** 浏览器类型 */
+    private String browser;
+
+    /** 操作系统 */
+    private String os;
+
+    /** 提示消息 */
+    private String msg;
+
+    /** 访问时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date loginTime;
+
+    public Long getInfoId()
+    {
+        return infoId;
+    }
+
+    public void setInfoId(Long infoId)
+    {
+        this.infoId = infoId;
+    }
+
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+
+    public String getStatus()
+    {
+        return status;
+    }
+
+    public void setStatus(String status)
+    {
+        this.status = status;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public String getMsg()
+    {
+        return msg;
+    }
+
+    public void setMsg(String msg)
+    {
+        this.msg = msg;
+    }
+
+    public Date getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Date loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+}

+ 71 - 0
backend/src/main/java/com/jiayue/ssi/factory/LoginFactory.java

@@ -0,0 +1,71 @@
+package com.jiayue.ssi.factory;
+
+import com.jiayue.ssi.constant.Constants;
+import com.jiayue.ssi.entity.SysLogininfor;
+import com.jiayue.ssi.service.SysLogininforService;
+import com.jiayue.ssi.util.*;
+import eu.bitwalker.useragentutils.UserAgent;
+
+import java.util.Date;
+
+
+/**
+* 登录日志工厂
+*
+* @author xsl
+* @since 2023/03/29
+*/
+public class LoginFactory {
+    /**
+     * 记录登录信息
+     *
+     * @param username 用户名
+     * @param status 状态
+     * @param message 消息
+     * @return 任务task
+     */
+    public static void recordLogininfor(final String username, final String status, final String message) {
+        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+        final String ip = IPUtils.getIpAddr();
+        String address = AddressUtils.getRealAddressByIP(ip);
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock(ip));
+        s.append(address);
+        s.append(getBlock(username));
+        s.append(getBlock(status));
+        s.append(getBlock(message));
+        // 获取客户端操作系统
+        String os = userAgent.getOperatingSystem().getName();
+        // 获取客户端浏览器
+        String browser = userAgent.getBrowser().getName();
+        // 封装对象
+        SysLogininfor logininfor = new SysLogininfor();
+        logininfor.setUserName(username);
+        logininfor.setIpaddr(ip);
+        logininfor.setLoginLocation(address);
+        logininfor.setBrowser(browser);
+        logininfor.setOs(os);
+        logininfor.setMsg(message);
+        logininfor.setLoginTime(new Date());
+        // 日志状态
+        if (RyStringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
+        {
+            logininfor.setStatus(Constants.SUCCESS);
+        }
+        else if (Constants.LOGIN_FAIL.equals(status))
+        {
+            logininfor.setStatus(Constants.FAIL);
+        }
+        // 插入数据
+        SpringUtils.getBean(SysLogininforService.class).save(logininfor);
+    }
+
+    public static String getBlock(Object msg)
+    {
+        if (msg == null)
+        {
+            msg = "";
+        }
+        return "[" + msg.toString() + "]";
+    }
+}

+ 10 - 0
backend/src/main/java/com/jiayue/ssi/filter/MailCodeFilter.java

@@ -7,6 +7,8 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import com.jiayue.ssi.constant.Constants;
+import com.jiayue.ssi.factory.LoginFactory;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.core.annotation.Order;
 import org.springframework.web.filter.OncePerRequestFilter;
@@ -39,6 +41,8 @@ public class MailCodeFilter extends OncePerRequestFilter {
 
                 // 校验服务端验证码
                 if (mailCode == null || "".equals(mailCode)) {
+                    // 记录用户失败日志
+                    LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "邮箱口令错误");
                     response.addHeader("Access-Control-Allow-Origin", "*");
                     response.setContentType("text/html;charset=UTF-8");
                     response.setStatus(401);
@@ -50,6 +54,8 @@ public class MailCodeFilter extends OncePerRequestFilter {
 
                 // 校验页面验证码
                 if (StringUtils.isEmpty(mailbox)) {
+                    // 记录用户失败日志
+                    LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "邮箱口令错误");
                     response.addHeader("Access-Control-Allow-Origin", "*");
                     response.setContentType("text/html;charset=UTF-8");
                     response.setStatus(401);
@@ -57,6 +63,8 @@ public class MailCodeFilter extends OncePerRequestFilter {
                     return;
                 }
                 if (mailbox.length() != 6) {
+                    // 记录用户失败日志
+                    LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "邮箱口令错误");
                     response.addHeader("Access-Control-Allow-Origin", "*");
                     response.setContentType("text/html;charset=UTF-8");
                     response.setStatus(401);
@@ -64,6 +72,8 @@ public class MailCodeFilter extends OncePerRequestFilter {
                     return;
                 }
                 if (!String.valueOf(mailCode).toLowerCase().equals(mailbox.toLowerCase())) {
+                    // 记录用户失败日志
+                    LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "邮箱口令错误");
                     // 删除缓存邮箱口令
                     LocalCache.remove(CacheConstants.MAIL_CODE_KEY + username);
                     response.addHeader("Access-Control-Allow-Origin", "*");

+ 11 - 0
backend/src/main/java/com/jiayue/ssi/filter/VerifyCodeFilter.java

@@ -7,6 +7,8 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import com.jiayue.ssi.constant.Constants;
+import com.jiayue.ssi.factory.LoginFactory;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.core.annotation.Order;
 import org.springframework.web.filter.OncePerRequestFilter;
@@ -31,11 +33,14 @@ public class VerifyCodeFilter extends OncePerRequestFilter {
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
         if ("POST".equalsIgnoreCase(request.getMethod()) && defaultFilterProcessUrl.equals(request.getServletPath())) {
             // 验证码验证
+            String username = request.getParameter("username");
             String requestCaptcha = request.getParameter("code");
             String verifyuuid = request.getParameter("verifyuuid");
             Object uuidObj = LocalCache.get(CacheConstants.CAPTCHA_CODE_KEY + verifyuuid);
             // 校验服务端验证码
             if (uuidObj==null || "".equals(uuidObj)){
+                // 记录验证码失败日志
+                LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "验证码错误");
                 response.addHeader("Access-Control-Allow-Origin", "*");
                 response.setContentType("text/html;charset=UTF-8");
                 response.setStatus(401);
@@ -44,6 +49,8 @@ public class VerifyCodeFilter extends OncePerRequestFilter {
             }
             // 校验页面验证码
             if (StringUtils.isEmpty(requestCaptcha)) {
+                // 记录验证码失败日志
+                LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "验证码错误");
                 response.addHeader("Access-Control-Allow-Origin", "*");
                 response.setContentType("text/html;charset=UTF-8");
                 response.setStatus(401);
@@ -51,6 +58,8 @@ public class VerifyCodeFilter extends OncePerRequestFilter {
                 return;
             }
             if (requestCaptcha.length()!=4){
+                // 记录验证码失败日志
+                LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "验证码错误");
                 response.addHeader("Access-Control-Allow-Origin", "*");
                 response.setContentType("text/html;charset=UTF-8");
                 response.setStatus(401);
@@ -58,6 +67,8 @@ public class VerifyCodeFilter extends OncePerRequestFilter {
                 return;
             }
             if (!String.valueOf(uuidObj).toLowerCase().equals(requestCaptcha.toLowerCase())) {
+                // 记录验证码失败日志
+                LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "验证码错误");
                 // 删除缓存验证码
                 LocalCache.remove(CacheConstants.CAPTCHA_CODE_KEY + verifyuuid);
                 response.addHeader("Access-Control-Allow-Origin", "*");

+ 18 - 0
backend/src/main/java/com/jiayue/ssi/filter/VerifySmFilter.java

@@ -2,7 +2,9 @@ package com.jiayue.ssi.filter;
 
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.jiayue.ssi.constant.Constants;
 import com.jiayue.ssi.constant.SecretKeyConstants;
+import com.jiayue.ssi.factory.LoginFactory;
 import com.jiayue.ssi.servlet.ParameterRequestWrapper;
 import com.jiayue.ssi.util.JwtTokenUtil;
 import com.jiayue.ssi.util.ResponseInfo;
@@ -88,6 +90,10 @@ public class VerifySmFilter extends OncePerRequestFilter {
                         decryptStr = SM2CryptUtils.decrypt(data_sm2, SecretKeyConstants.SERVER_PRIVATE_KEY);
                     } catch (Exception e) {
                         // 参数验签失败
+                        if (defaultFilterProcessUrl.equals(request.getServletPath())){
+                            // 记录用户退出日志
+                            LoginFactory.recordLogininfor("未知", Constants.LOGIN_FAIL, "参数解密失败");
+                        }
                         ResponseInfo.doResponse(response, "参数解密失败,不能访问系统!", 401);
                         return;
                     }
@@ -98,12 +104,20 @@ public class VerifySmFilter extends OncePerRequestFilter {
                         boolean verifySign =
                             SM2CryptUtils.verifySign(SecretKeyConstants.CLIENT_PUBLIC_KEY, decryptStr, paramSign);
                         if (!verifySign) {
+                            if (defaultFilterProcessUrl.equals(request.getServletPath())){
+                                // 记录用户退出日志
+                                LoginFactory.recordLogininfor("未知", Constants.LOGIN_FAIL, "参数验签失败");
+                            }
                             // 验签失败
                             ResponseInfo.doResponse(response, "参数验签失败,不能访问系统!", 401);
                             return;
                         }
                     } catch (Exception e) {
                         // 验签失败
+                        if (defaultFilterProcessUrl.equals(request.getServletPath())){
+                            // 记录用户退出日志
+                            LoginFactory.recordLogininfor("未知", Constants.LOGIN_FAIL, "参数验签失败");
+                        }
                         ResponseInfo.doResponse(response, "参数验签失败,不能访问系统!", 401);
                         return;
                     }
@@ -112,6 +126,10 @@ public class VerifySmFilter extends OncePerRequestFilter {
                             stringToMap = JSONUtil.parseObj(decryptStr);
                         }
                         catch (Exception e){
+                            if (defaultFilterProcessUrl.equals(request.getServletPath())){
+                                // 记录用户退出日志
+                                LoginFactory.recordLogininfor("未知", Constants.LOGIN_FAIL, "参数转换json失败");
+                            }
                             ResponseInfo.doResponse(response, "参数不能转换json格式,不能访问系统!", 401);
                             return;
                         }

+ 4 - 0
backend/src/main/java/com/jiayue/ssi/handler/CustomAuthenticationFailureHandler.java

@@ -7,8 +7,10 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import com.jiayue.ssi.constant.CacheConstants;
+import com.jiayue.ssi.constant.Constants;
 import com.jiayue.ssi.constant.LoginConstants;
 import com.jiayue.ssi.entity.SysUser;
+import com.jiayue.ssi.factory.LoginFactory;
 import com.jiayue.ssi.service.SysParameterService;
 import com.jiayue.ssi.service.SysUserService;
 import com.jiayue.ssi.util.LocalCache;
@@ -88,6 +90,8 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
                 }
             }
         }
+        // 记录用户退出日志
+        LoginFactory.recordLogininfor(username, Constants.LOGIN_FAIL, "登录失败");
 
         // 删除缓存邮箱口令
         LocalCache.remove(CacheConstants.MAIL_CODE_KEY + username);

+ 6 - 0
backend/src/main/java/com/jiayue/ssi/handler/CustomAuthenticationSuccessHandler.java

@@ -9,7 +9,9 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import com.jiayue.ssi.constant.CacheConstants;
+import com.jiayue.ssi.constant.Constants;
 import com.jiayue.ssi.constant.SecretKeyConstants;
+import com.jiayue.ssi.factory.LoginFactory;
 import com.jiayue.ssi.service.SysUserService;
 import com.jiayue.ssi.util.LocalCache;
 import com.jiayue.ssi.util.SM2CryptUtils;
@@ -53,6 +55,10 @@ public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthent
 
 
         SecurityContextHolder.getContext().setAuthentication(authentication);
+
+        // 记录用户退出日志
+        LoginFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
+
         String token = jwtTokenUtil.generateToken(sysUser);
         // 将token存储内存中,便于重复登录比对
         CacheConstants.LOGIN_TOKEN_MAP.put(username,token);

+ 51 - 0
backend/src/main/java/com/jiayue/ssi/handler/CustomLogoutSuccessHandler.java

@@ -0,0 +1,51 @@
+package com.jiayue.ssi.handler;
+
+import cn.hutool.json.JSONUtil;
+import com.jiayue.ssi.constant.CacheConstants;
+import com.jiayue.ssi.constant.Constants;
+import com.jiayue.ssi.constant.SecretKeyConstants;
+import com.jiayue.ssi.entity.SysUser;
+import com.jiayue.ssi.factory.LoginFactory;
+import com.jiayue.ssi.util.ResponseVO;
+import com.jiayue.ssi.util.SM2CryptUtils;
+import com.jiayue.ssi.util.SecurityContextUtil;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.Authentication;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 自定义退出处理类 返回成功
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class CustomLogoutSuccessHandler implements org.springframework.security.web.authentication.logout.LogoutSuccessHandler {
+    /**
+     * 退出处理
+     *
+     * @return
+     */
+    @Override
+    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+            throws IOException, ServletException {
+        SysUser sysUser = (SysUser)authentication.getPrincipal();
+        // 记录用户退出日志
+        LoginFactory.recordLogininfor(sysUser.getUsername(), Constants.LOGIN_SUCCESS, "退出成功");
+        // 将token存储内存中,便于重复登录比对
+        CacheConstants.LOGIN_TOKEN_MAP.remove(sysUser.getUsername());
+
+        String obj = JSONUtil.toJsonStr(ResponseVO.success("退出成功"));
+        // token加密处理
+        String encrypt = SM2CryptUtils.encrypt(obj, SecretKeyConstants.CLIENT_PUBLIC_KEY);
+        // token签名
+        String signStr = SM2CryptUtils.sign(SecretKeyConstants.SERVER_PRIVATE_KEY,obj);
+        String secretResult = "encrypt="+encrypt+"&signStr="+signStr;
+        response.addHeader("Access-Control-Allow-Origin", "*");
+        response.setContentType("text/html;charset=UTF-8");
+        response.setStatus(200);
+        response.getWriter().write(secretResult);
+    }
+}

+ 48 - 0
backend/src/main/java/com/jiayue/ssi/mapper/SysLogininforMapper.java

@@ -0,0 +1,48 @@
+package com.jiayue.ssi.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jiayue.ssi.entity.SysLogininfor;
+import com.jiayue.ssi.entity.SysMenu;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ *  系统访问记录表
+ *
+ * @author xsl
+ * @since 2023-03-17
+ */
+@Mapper
+public interface SysLogininforMapper extends BaseMapper<SysLogininfor> {
+    /**
+     * 新增系统登录日志
+     *
+     * @param logininfor 访问日志对象
+     */
+    public void insertLogininfor(SysLogininfor logininfor);
+
+    /**
+     * 查询系统登录日志集合
+     *
+     * @param logininfor 访问日志对象
+     * @return 登录记录集合
+     */
+    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+    /**
+     * 批量删除系统登录日志
+     *
+     * @param infoIds 需要删除的登录日志ID
+     * @return 结果
+     */
+    public int deleteLogininforByIds(Long[] infoIds);
+
+    /**
+     * 清空系统登录日志
+     *
+     * @return 结果
+     */
+    public int cleanLogininfor();
+}

+ 0 - 2
backend/src/main/java/com/jiayue/ssi/mapper/SysMenuMapper.java

@@ -8,9 +8,7 @@ import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 /**
- * <p>
  *  菜单管理Mapper
- * </p>
  *
  * @author xsl
  * @since 2023-03-17

+ 0 - 2
backend/src/main/java/com/jiayue/ssi/mapper/SysParameterMapper.java

@@ -7,9 +7,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.jiayue.ssi.entity.SysUser;
 
 /**
- * <p>
  *  参数管理Mapper
- * </p>
  *
  * @author xsl
  * @since 2023-03-17

+ 7 - 7
backend/src/main/java/com/jiayue/ssi/mapper/SysRoleMapper.java

@@ -106,13 +106,13 @@ public interface SysRoleMapper extends BaseMapper<SysRole> {
 //     */
 //    public int insertRole(SysRole role);
 //
-//    /**
-//     * 通过角色ID删除角色
-//     *
-//     * @param roleId 角色ID
-//     * @return 结果
-//     */
-//    public int deleteRoleById(Long roleId);
+    /**
+     * 通过角色ID删除角色
+     * @param update_by 修改人
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    public int deleteRoleById(String update_by,Long roleId);
 //
 //    /**
 //     * 批量删除角色信息

+ 0 - 2
backend/src/main/java/com/jiayue/ssi/mapper/SysUserMapper.java

@@ -5,9 +5,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
- * <p>
  *  用户管理Mapper
- * </p>
  *
  * @author xsl
  * @since 2023-03-10

+ 42 - 0
backend/src/main/java/com/jiayue/ssi/service/SysLogininforService.java

@@ -0,0 +1,42 @@
+package com.jiayue.ssi.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jiayue.ssi.entity.SysLogininfor;
+import com.jiayue.ssi.entity.SysMenu;
+
+import java.util.List;
+
+/**
+ * 系统访问日志情况信息 服务层
+ *
+ * @author ruoyi
+ */
+public interface SysLogininforService extends IService<SysLogininfor> {
+//    /**
+//     * 新增系统登录日志
+//     *
+//     * @param logininfor 访问日志对象
+//     */
+//    public void insertLogininfor(SysLogininfor logininfor);
+//
+//    /**
+//     * 查询系统登录日志集合
+//     *
+//     * @param logininfor 访问日志对象
+//     * @return 登录记录集合
+//     */
+//    public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+//
+//    /**
+//     * 批量删除系统登录日志
+//     *
+//     * @param infoIds 需要删除的登录日志ID
+//     * @return 结果
+//     */
+//    public int deleteLogininforByIds(Long[] infoIds);
+//
+//    /**
+//     * 清空系统登录日志
+//     */
+//    public void cleanLogininfor();
+}

+ 8 - 15
backend/src/main/java/com/jiayue/ssi/service/SysRoleService.java

@@ -126,21 +126,14 @@ public interface SysRoleService extends IService<SysRole> {
 //     */
 //    public int authDataScope(SysRole role);
 //
-//    /**
-//     * 通过角色ID删除角色
-//     *
-//     * @param roleId 角色ID
-//     * @return 结果
-//     */
-//    public int deleteRoleById(Long roleId);
-//
-//    /**
-//     * 批量删除角色信息
-//     *
-//     * @param roleIds 需要删除的角色ID
-//     * @return 结果
-//     */
-//    public int deleteRoleByIds(Long[] roleIds);
+    /**
+     * 通过角色ID删除角色
+     *
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    public int deleteRoleById(Long roleId);
+
 //
 //    /**
 //     * 取消授权用户角色

+ 21 - 0
backend/src/main/java/com/jiayue/ssi/service/impl/SysLogininforServiceImpl.java

@@ -0,0 +1,21 @@
+package com.jiayue.ssi.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.ssi.entity.SysLogininfor;
+import com.jiayue.ssi.entity.SysMenu;
+import com.jiayue.ssi.mapper.SysLogininforMapper;
+import com.jiayue.ssi.mapper.SysMenuMapper;
+import com.jiayue.ssi.service.SysLogininforService;
+import com.jiayue.ssi.service.SysMenuService;
+import org.springframework.stereotype.Service;
+
+/**
+*
+*
+* @author xsl
+* @since 2023/03/29
+*/
+@Service
+public class SysLogininforServiceImpl  extends ServiceImpl<SysLogininforMapper, SysLogininfor> implements SysLogininforService {
+
+}

+ 26 - 56
backend/src/main/java/com/jiayue/ssi/service/impl/SysRoleServiceImpl.java

@@ -40,8 +40,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
      */
     @Override
     @Transactional
-    public int insertRole(SysRole role)
-    {
+    public int insertRole(SysRole role) {
         // 新增角色信息
         roleMapper.insertRole(role);
         return insertRoleMenu(role);
@@ -53,13 +52,11 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
      *
      * @param role 角色对象
      */
-    public int insertRoleMenu(SysRole role)
-    {
+    public int insertRoleMenu(SysRole role) {
         int rows = 1;
         // 新增用户与角色管理
         List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
-        for (Long menuId : role.getMenuIds())
-        {
+        for (Long menuId : role.getMenuIds()) {
             SysRoleMenu rm = new SysRoleMenu();
             rm.setRoleId(role.getRoleId());
             rm.setMenuId(menuId);
@@ -68,8 +65,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
             rm.setCreateTime(new Date());
             list.add(rm);
         }
-        if (list.size() > 0)
-        {
+        if (list.size() > 0) {
             rows = roleMenuMapper.batchRoleMenu(list);
         }
         return rows;
@@ -170,6 +166,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
 //        return roleMapper.selectRoleListByUserId(userId);
 //    }
 //
+
     /**
      * 通过角色ID查询角色
      *
@@ -177,10 +174,10 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
      * @return 角色对象信息
      */
     @Override
-    public SysRole selectRoleById(Long roleId)
-    {
+    public SysRole selectRoleById(Long roleId) {
         return this.getById(roleId);
     }
+
     /**
      * 修改保存角色信息
      *
@@ -189,12 +186,11 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
      */
     @Override
     @Transactional
-    public int updateRole(SysRole role)
-    {
+    public int updateRole(SysRole role) {
         // 修改角色信息
         this.updateById(role);
         // 删除角色与菜单关联
-        roleMenuMapper.deleteRoleMenuByRoleId(SecurityContextUtil.getSysUser().getUsername(),role.getRoleId());
+        roleMenuMapper.deleteRoleMenuByRoleId(SecurityContextUtil.getSysUser().getUsername(), role.getRoleId());
         return insertRoleMenu(role);
     }
 //
@@ -390,49 +386,23 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
 //        return rows;
 //    }
 //
-//    /**
-//     * 通过角色ID删除角色
-//     *
-//     * @param roleId 角色ID
-//     * @return 结果
-//     */
-//    @Override
-//    @Transactional
-//    public int deleteRoleById(Long roleId)
-//    {
-//        // 删除角色与菜单关联
-//        roleMenuMapper.deleteRoleMenuByRoleId(roleId);
-//        // 删除角色与部门关联
-//        roleDeptMapper.deleteRoleDeptByRoleId(roleId);
-//        return roleMapper.deleteRoleById(roleId);
-//    }
-//
-//    /**
-//     * 批量删除角色信息
-//     *
-//     * @param roleIds 需要删除的角色ID
-//     * @return 结果
-//     */
-//    @Override
-//    @Transactional
-//    public int deleteRoleByIds(Long[] roleIds)
-//    {
-//        for (Long roleId : roleIds)
-//        {
-//            checkRoleAllowed(new SysRole(roleId));
-//            checkRoleDataScope(roleId);
-//            SysRole role = selectRoleById(roleId);
-//            if (countUserRoleByRoleId(roleId) > 0)
-//            {
-//                throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
-//            }
-//        }
-//        // 删除角色与菜单关联
-//        roleMenuMapper.deleteRoleMenu(roleIds);
-//        // 删除角色与部门关联
-//        roleDeptMapper.deleteRoleDept(roleIds);
-//        return roleMapper.deleteRoleByIds(roleIds);
-//    }
+
+    /**
+     * 通过角色ID删除角色
+     *
+     * @param roleId 角色ID
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public int deleteRoleById(Long roleId) {
+        String username = SecurityContextUtil.getSysUser().getUsername();
+        // 删除角色与菜单关联
+        roleMenuMapper.deleteRoleMenuByRoleId(username, roleId);
+        return roleMapper.deleteRoleById(username, roleId);
+    }
+
+
 //
 //    /**
 //     * 取消授权用户角色

+ 50 - 0
backend/src/main/java/com/jiayue/ssi/util/AddressUtils.java

@@ -0,0 +1,50 @@
+package com.jiayue.ssi.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 获取地址类
+ *
+ * @author ruoyi
+ */
+public class AddressUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
+
+    // IP地址查询
+    public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
+
+    // 未知地址
+    public static final String UNKNOWN = "XX XX";
+
+    public static String getRealAddressByIP(String ip)
+    {
+        // 内网不查询
+        if (IPUtils.internalIp(ip))
+        {
+            return "内网IP";
+        }
+//        if (RuoYiConfig.isAddressEnabled())
+//        {
+//            try
+//            {
+//                String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
+//                if (StringUtils.isEmpty(rspStr))
+//                {
+//                    log.error("获取地理位置异常 {}", ip);
+//                    return UNKNOWN;
+//                }
+//                JSONObject obj = JSON.parseObject(rspStr);
+//                String region = obj.getString("pro");
+//                String city = obj.getString("city");
+//                return String.format("%s %s", region, city);
+//            }
+//            catch (Exception e)
+//            {
+//                log.error("获取地理位置异常 {}", ip);
+//            }
+//        }
+        return UNKNOWN;
+    }
+}

+ 219 - 0
backend/src/main/java/com/jiayue/ssi/util/ServletUtils.java

@@ -0,0 +1,219 @@
+package com.jiayue.ssi.util;
+
+import cn.hutool.core.convert.Convert;
+import com.jiayue.ssi.constant.Constants;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 客户端工具类
+ *
+ * @author ruoyi
+ */
+public class ServletUtils
+{
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name)
+    {
+        return getRequest().getParameter(name);
+    }
+
+    /**
+     * 获取String参数
+     */
+    public static String getParameter(String name, String defaultValue)
+    {
+        return Convert.toStr(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name)
+    {
+        return Convert.toInt(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Integer参数
+     */
+    public static Integer getParameterToInt(String name, Integer defaultValue)
+    {
+        return Convert.toInt(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name)
+    {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue)
+    {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获得所有请求参数
+     *
+     * @param request 请求对象{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String[]> getParams(ServletRequest request)
+    {
+        final Map<String, String[]> map = request.getParameterMap();
+        return Collections.unmodifiableMap(map);
+    }
+
+    /**
+     * 获得所有请求参数
+     *
+     * @param request 请求对象{@link ServletRequest}
+     * @return Map
+     */
+    public static Map<String, String> getParamMap(ServletRequest request)
+    {
+        Map<String, String> params = new HashMap<>();
+        for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
+        {
+            params.put(entry.getKey(), RyStringUtils.join(entry.getValue(), ","));
+        }
+        return params;
+    }
+
+    /**
+     * 获取request
+     */
+    public static HttpServletRequest getRequest()
+    {
+        return getRequestAttributes().getRequest();
+    }
+
+    /**
+     * 获取response
+     */
+    public static HttpServletResponse getResponse()
+    {
+        return getRequestAttributes().getResponse();
+    }
+
+    /**
+     * 获取session
+     */
+    public static HttpSession getSession()
+    {
+        return getRequest().getSession();
+    }
+
+    public static ServletRequestAttributes getRequestAttributes()
+    {
+        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+        return (ServletRequestAttributes) attributes;
+    }
+
+    /**
+     * 将字符串渲染到客户端
+     *
+     * @param response 渲染对象
+     * @param string 待渲染的字符串
+     */
+    public static void renderString(HttpServletResponse response, String string)
+    {
+        try
+        {
+            response.setStatus(200);
+            response.setContentType("application/json");
+            response.setCharacterEncoding("utf-8");
+            response.getWriter().print(string);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 是否是Ajax异步请求
+     *
+     * @param request
+     */
+    public static boolean isAjaxRequest(HttpServletRequest request)
+    {
+        String accept = request.getHeader("accept");
+        if (accept != null && accept.contains("application/json"))
+        {
+            return true;
+        }
+
+        String xRequestedWith = request.getHeader("X-Requested-With");
+        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
+        {
+            return true;
+        }
+
+        String uri = request.getRequestURI();
+        if (RyStringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+        {
+            return true;
+        }
+
+        String ajax = request.getParameter("__ajax");
+        return RyStringUtils.inStringIgnoreCase(ajax, "json", "xml");
+    }
+
+    /**
+     * 内容编码
+     *
+     * @param str 内容
+     * @return 编码后的内容
+     */
+    public static String urlEncode(String str)
+    {
+        try
+        {
+            return URLEncoder.encode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return RyStringUtils.EMPTY;
+        }
+    }
+
+    /**
+     * 内容解码
+     *
+     * @param str 内容
+     * @return 解码后的内容
+     */
+    public static String urlDecode(String str)
+    {
+        try
+        {
+            return URLDecoder.decode(str, Constants.UTF8);
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            return RyStringUtils.EMPTY;
+        }
+    }
+}

+ 157 - 0
backend/src/main/java/com/jiayue/ssi/util/SpringUtils.java

@@ -0,0 +1,157 @@
+package com.jiayue.ssi.util;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring工具类 方便在非spring管理环境中获取bean
+ *
+ * @author ruoyi
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
+{
+    /** Spring应用上下文环境 */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+    {
+        SpringUtils.applicationContext = applicationContext;
+    }
+
+    /**
+     * 获取对象
+     *
+     * @param name
+     * @return Object 一个以所给名字注册的bean的实例
+     * @throws BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @param clz
+     * @return
+     * @throws BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = (T) beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name
+     * @return boolean
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 注册对象的类型
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name
+     * @return
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 获取aop代理对象
+     *
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 获取当前的环境配置,无配置返回null
+     *
+     * @return 当前的环境配置
+     */
+    public static String[] getActiveProfiles()
+    {
+        return applicationContext.getEnvironment().getActiveProfiles();
+    }
+
+    /**
+     * 获取当前的环境配置,当有多个环境配置时,只获取第一个
+     *
+     * @return 当前的环境配置
+     */
+    public static String getActiveProfile()
+    {
+        final String[] activeProfiles = getActiveProfiles();
+        return RyStringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
+    }
+
+    /**
+     * 获取配置文件中的值
+     *
+     * @param key 配置文件的key
+     * @return 当前的配置文件的值
+     *
+     */
+    public static String getRequiredProperty(String key)
+    {
+        return applicationContext.getEnvironment().getRequiredProperty(key);
+    }
+}

+ 2 - 9
backend/src/main/resources/mapper/system/SysRoleMapper.xml

@@ -140,15 +140,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  		where role_id = #{roleId} and del_flag=0
 	</update>
 
-	<delete id="deleteRoleById" parameterType="Long">
- 		update sys_role set del_flag = '2' where role_id = #{roleId}
- 	</delete>
-
- 	<delete id="deleteRoleByIds" parameterType="Long">
- 	    update sys_role set del_flag = '2' where role_id in
- 		<foreach collection="array" item="roleId" open="(" separator="," close=")">
- 			#{roleId}
-        </foreach>
+	<delete id="deleteRoleById">
+ 		update sys_role set del_flag = '1',update_by=#{update_by},update_time=sysdate() where role_id = #{roleId}
  	</delete>
 
 </mapper>

+ 9 - 3
ui/src/layout/components/Navbar.vue

@@ -94,9 +94,15 @@ export default {
       this.$store.dispatch('app/toggleSideBar')
     },
     async logout() {
-      removeToken()
-      //注销返回自己的登录页
-      this.$router.push(`/login?redirect=${this.$route.fullPath}`)
+      this.$axios.post(
+        '/logout',{}
+      ).then((res) => {
+        this.$message.success(res.data)
+        removeToken()
+        //注销返回自己的登录页
+        this.$router.push(`/login?redirect=${this.$route.fullPath}`)
+      })
+
       // this.$confirm('确定注销并退出系统吗?', '提示', {
       //   confirmButtonText: '确定',
       //   cancelButtonText: '取消',

+ 1 - 0
ui/src/views/login/index.vue

@@ -256,6 +256,7 @@ export default {
           }
           this.$axios.post('/user/login', param).then((res) => {
             sessionStorage.setItem('token', res.data)
+            // 清空路由菜单
             store.commit('SET_R', [])
             this.$router.push('/')
             this.loading = false

+ 44 - 12
ui/src/views/sysManager/roleManager/index.vue

@@ -602,22 +602,54 @@ export default {
       }
     },
     /** 删除按钮操作 */
-    handleDelete(row) {
-      const roleIds = row.roleId || this.ids;
-      this.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function () {
-        return delRole(roleIds);
+    handleDelete(){
+      const _selectData = this.$refs.xTable.getRadioRecord(true)
+      if (_selectData == null) {
+        this.$message({
+          type: 'warning',
+          message: '请选择记录!'
+        });
+        return
+      }
+      this.$confirm('是否确认删除角色?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
       }).then(() => {
-        this.getList();
-        this.$modal.msgSuccess("删除成功");
+        this.doDelete(_selectData)
       }).catch(() => {
       });
     },
-    /** 导出按钮操作 */
-    handleExport() {
-      this.download('system/role/export', {
-        ...this.queryParams
-      }, `role_${new Date().getTime()}.xlsx`)
-    }
+    /**
+     * 删除提交
+     */
+    doDelete:debounce(function(_selectData){
+      console.log(_selectData)
+      const param = {
+        roleId: _selectData.roleId
+      }
+      this.$axios.post('/sysRoleController/delRole', param).then((res) => {
+        if (res.code == 0) {
+          this.$message({
+            type: 'success',
+            message: '删除成功!'
+          });
+          this.getList();
+        } else {
+          this.$message({
+            type: 'error',
+            message: res.data
+          });
+        }
+      }).catch((error) => {
+        this.$message({
+          type: 'error',
+          message: '删除失败!'
+        });
+        console.log(error)
+        this.loading = false
+      })
+    },1000)
   }
 };
 </script>