whyclxw
2024-07-01 db23586fd744582cd8ee237c34ff29d9277009ee
用户管理添加
5个文件已修改
27个文件已添加
2141 ■■■■■ 已修改文件
pom.xml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/App.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/anotation/Realm.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/config/CaffeineConfig.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/config/ShiroConfig.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/constant/OperationLogEnum.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/constant/YamlProperties.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/IndexController.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/LoginController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/OperationLogController.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/controller/UserInfController.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/filter/RolesOrAuthorizationFilter.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/mapper/DocUserMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/mapper/OperationLogMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/mapper/UserInfMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/pojo/OperationLog.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/pojo/UserInf.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/properties/LinkProperties.java 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/properties/PropertiesUtil.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/realm/CustomRealm.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/OperationLogService.java 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/UserBridgeService.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/UserInfService.java 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/HttpUtil.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/JasyptUtils.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/MD5Util.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/RSAUtil.java 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/util/UserUtil.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/webSocket/LoginCheckSocket.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/config/application-dev.yml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/config/application-prod.yml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/UserInfMapper.xml 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -106,6 +106,33 @@
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-starter</artifactId>
            <version>1.5.3</version>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.15</version>
        </dependency>
        <dependency>
            <groupId>com.github.ulisesbocchio</groupId>
            <artifactId>jasypt-spring-boot-starter</artifactId>
            <version>3.0.4</version>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.3.9</version>
        </dependency>
        <!--<dependency>
            <groupId>org.springframework.plugin</groupId>
            <artifactId>spring-plugin-core</artifactId>
@@ -137,6 +164,8 @@
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    <build>
src/main/java/com/whyc/App.java
@@ -16,7 +16,7 @@
@EnableWebMvc
@ServletComponentScan(basePackages = {"com.whyc.filter","com.whyc.servlet","com.whyc.listener"})
@EnableCaching
public class App extends WebMvcConfigurerAdapter  implements WebMvcConfigurer {
public class App  {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
src/main/java/com/whyc/anotation/Realm.java
New file
@@ -0,0 +1,20 @@
package com.whyc.anotation;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface Realm {
    @AliasFor(
            annotation = Component.class
    )
    String value() default "";
}
src/main/java/com/whyc/config/CaffeineConfig.java
New file
@@ -0,0 +1,89 @@
package com.whyc.config;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.ArrayList;
/**
 * Caffeine配置
 */
@Configuration
public class CaffeineConfig {
    public static enum Caches{
        defaultCache(500),
        defaultCache2Exp(500,24)
        ;
        Caches() {
        }
        Caches(int maxSize) {
            this.maxSize = maxSize;
        }
        Caches(int maxSize, int ttl) {
            this.maxSize = maxSize;
            this.ttl = ttl;
        }
        private int maxSize;
        private int ttl;
        public int getMaxSize() {
            return maxSize;
        }
        public void setMaxSize(int maxSize) {
            this.maxSize = maxSize;
        }
        public int getTtl() {
            return ttl;
        }
        public void setTtl(int ttl) {
            this.ttl = ttl;
        }
    }
    @Bean
    @Primary
    public CacheManager caffeineCacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        ArrayList<CaffeineCache> caffeineCaches = new ArrayList<>();
        for (Caches cache : Caches.values()) {
            caffeineCaches.add(new CaffeineCache(cache.name(),
                    Caffeine.newBuilder().recordStats()
                    .maximumSize(cache.getMaxSize())
                    .build()
            ));
        }
        cacheManager.setCaches(caffeineCaches);
        return cacheManager;
    }
    /*@Bean(value = "defaultCache")
    public Cache<String,Object> defaultCache(){
        return Caffeine.newBuilder().recordStats()
                        .maximumSize(Caches.defaultCache.getMaxSize())
                        .build();
    }
    @Bean(value = "defaultCache2Exp")
    public Cache<String,Object> defaultCache2Exp(){
        return Caffeine.newBuilder().recordStats()
                        .maximumSize(Caches.defaultCache2Exp.getMaxSize())
                        .expireAfterWrite(Caches.defaultCache2Exp.ttl, TimeUnit.HOURS)
                        .build();
    }*/
}
src/main/java/com/whyc/config/ShiroConfig.java
New file
@@ -0,0 +1,124 @@
package com.whyc.config;
import com.whyc.constant.YamlProperties;
import com.whyc.filter.RolesOrAuthorizationFilter;
import com.whyc.properties.PropertiesUtil;
import com.whyc.realm.CustomRealm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
 * 暂时提供权限管理,会话管理后续更新 TODO
 */
@Configuration
//@Log4j2
@DependsOn("yamlProperties")
public class ShiroConfig {
    @Autowired
    CustomRealm customRealm;
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
        cookie.setHttpOnly(false);
        cookie.setSameSite(Cookie.SameSiteOptions.NONE);
        cookie.setSecure(true);
        cookie.setName("MSManager");
        sessionManager.setSessionIdCookie(cookie);
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(true);
        return sessionManager;
    }
    /**权限管理器*/
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(customRealm);
        if(YamlProperties.runModel == 1){
            securityManager.setSessionManager(sessionManager());
        }
        return securityManager;
    }
    /**
     * 保证实现Shiro内部lifecycle函数的bean执行
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor(){
        return new  LifecycleBeanPostProcessor();
    }
    /**AOP式方法级权限检验*/
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    /**配合DefaultAdvisorAutoProxyCreator 注解权限校验*/
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(defaultWebSecurityManager());
        return aasa;
    }
    /**过滤器链*/
    private Map<String, String> filterChainDefinition(){
        List<Object> list  = PropertiesUtil.propertiesShiro.getKeyList();
        Map<String, String> map = new LinkedHashMap<>();
        for (Object object : list) {
            String key = object.toString();
            String value = PropertiesUtil.getShiroValue(key);
            //log.info("读取防止盗链控制:---key{},---value:{}",key,value);
            map.put(key, value);
        }
        return map;
    }
    /**自定义过滤器*/
    private Map<String, Filter> filters(){
        HashMap<String, Filter> map = new HashMap<>();
        map.put("rolesOr",new RolesOrAuthorizationFilter());
        return map;
    }
    /**过滤器*/
//    @Bean("shiroFilter")
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        //注入新定义的过滤器
        shiroFilter.setFilters(filters());
        shiroFilter.setSecurityManager(defaultWebSecurityManager());
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinition());
        shiroFilter.setLoginUrl("/login.html");
        //shiroFilter.setLoginUrl("/index.html#login");
        shiroFilter.setUnauthorizedUrl("/login/unauthorized");
        return shiroFilter;
    }
}
src/main/java/com/whyc/constant/OperationLogEnum.java
New file
@@ -0,0 +1,50 @@
package com.whyc.constant;
/**
 * 审计日志/操作日志 操作类型定义
 */
public enum OperationLogEnum {
    TYPE_1_SYS(10,"系统级事件"),
    TYPE_1_SERVICE(20,"业务级事件"),
    //子级别-系统级
    TYPE_2_LOGIN(101,"用户登录"),
    TYPE_2_LOGIN_FAIL(102,"用户登录失败"),
    TYPE_2_LOGOUT(103,"用户退出"),
    TYPE_2_USER_UPDATE(104,"用户信息修改"),
    TYPE_2_USER_ADD(105,"用户信息增加"),
    TYPE_2_USER_DELETE(106,"用户信息删除"),
    TYPE_2_USER_UPDATE_PASSWORD(107,"密码重置"),
    TYPE_2_UNAUTHORIZED_ACCESS(108,"越权访问"),
    TYPE_2_CONNECTION_TIMEOUT(109,"连接超时"),
    TYPE_2_EXCEPTION(110,"调用异常"),
    //子级别-业务级
    TYPE_2_POWER_UPDATE(201,"电源设备设置"),
    TYPE_2_BATTERY_UPDATE(202,"核容设备信息相关设置"),
    TYPE_2_BATTERY_TEST_PARAM_UPDATE(203,"核容设备遥调遥控"),
    TYPE_2_ALARM(204,"告警相关设置"),
    TYPE_2_BREAKER(205,"断路器信息相关操作"),
    TYPE_2_BREAKER_CONTROL(206,"断路器控制相关操作"),
    TYPE_2_GATEWAY(207,"网关相关操作"),
    TYPE_2_POWER_MODE_CONTROL(208,"电源设备模块控制操作"),
    TYPE_2_POWER_MODE_PARAM(209,"电源设备模块参数操作"),
    ;
    private Integer type;
    private String name;
    OperationLogEnum(Integer type, String name) {
        this.type = type;
        this.name = name;
    }
    public Integer getType() {
        return type;
    }
    public String getName() {
        return name;
    }
}
src/main/java/com/whyc/constant/YamlProperties.java
@@ -22,41 +22,55 @@
    public static Integer systemType;
    /**人脸识别对比阈值*/
    public static Float faceThreshold;
    //public static Float faceThreshold;
    /**告警短信开关*/
    public static String messageSwitch;
   /* public static String messageSwitch;
    public static String messageSecretId;
    public static String messageSecretKey;
    public static String messageRegion;
    public static String messageSdkAppId;
    public static String messageSignName;
    public static String messageTemplateId;
    public static String appId4Win;
    public static String messageTemplateId;*/
   /* public static String appId4Win;
    public static String sdkKey4Win;
    public static String appId4Linux;
    public static String sdkKey4Linux;
    public static String activeKey;
    public static Integer faceType;
    public static String sdkKey4Linux;*/
    /**告警工单开关*/
    public static String alarmTaskSwitch;
    //public static String alarmTaskSwitch;
    /**系统运行模式*/
    public static Integer runModel;
    /**自定义常量*/
    public static String fontDynamicCodeSwitch;
    /**FTP信息*/
    /*public static String ftpIp;
    public static Integer ftpPort;
    public static String ftpUserName;
    public static String ftpPassword;*/
    /*====== 自定义信息 ======*/
    /**跨域白名单*/
    public static String allowedCORSDomainList;
    public static String restartPasswd;
    public static String publicKeyOld;
    public static String privateKeyOld;
    public static String publicKey;
    public static String privateKey;
    public static String aesDefaultKey;
    public static String aesIv;
    public static String i18nLanguage;
    @Value("${custom.rsa.publicKey}")
    public void setPublicKey(String publicKey) {
        YamlProperties.publicKey = publicKey;
    }
    @Value("${custom.rsa.privateKey}")
    public void setPrivateKey(String privateKey) {
        YamlProperties.privateKey = privateKey;
    }
    @Value("${custom.cors}")
    public void setAllowedCORSDomainList(String allowedCORSDomainList) {
        YamlProperties.allowedCORSDomainList = allowedCORSDomainList;
    }
    @Value("${spring.profiles.active}")
    public void setProfileType(String profileType) {
        YamlProperties.profileType = profileType;
@@ -66,23 +80,25 @@
    public void setSystemType(Integer systemType) {
        YamlProperties.systemType = systemType;
    }
    /* @Value("${custom.face.threshold}")
/*
    @Value("${custom.face.threshold}")
    private void setFaceThreshold(Float faceThreshold) {
        YamlProperties.faceThreshold = faceThreshold;
    }
    }*/
/*
   @Value("${custom.message.switch}")
    private void setMessageSwitch(String messageSwitch) {
        YamlProperties.messageSwitch = messageSwitch;
    }
    }*/
/*
    @Value("${custom.message.secret_id}")
    private void setMessageSecretId(String messageSecretId) {
        YamlProperties.messageSecretId = messageSecretId;
    }
*/
    @Value("${custom.message.secret_key}")
    /*@Value("${custom.message.secret_key}")
    private void setMessageSecretKey(String messageSecretKey) {
        YamlProperties.messageSecretKey = messageSecretKey;
    }
@@ -105,14 +121,14 @@
    @Value("${custom.message.templateId}")
    private void setMessageTemplateId(String messageTemplateId) {
        YamlProperties.messageTemplateId = messageTemplateId;
    }
    }*/
    @Value("${custom.alarm.task.switch}")
   /* @Value("${custom.alarm.task.switch}")
    private void setAlarmTaskSwitch(String alarmTaskSwitch) {
        YamlProperties.alarmTaskSwitch = alarmTaskSwitch;
    }
    @Value("${custom.face.appId4Win}")
*/
    /*@Value("${custom.face.appId4Win}")
    private void setAppId4Win(String appId4Win) {
        YamlProperties.appId4Win = appId4Win;
    }
@@ -130,70 +146,32 @@
    @Value("${custom.face.sdkKey4Linux}")
    private void setSdkKey4Linux(String sdkKey4Linux) {
        YamlProperties.sdkKey4Linux = sdkKey4Linux;
    }
    @Value("${custom.face.activeKey}")
    private void setActiveKey(String activeKey) {
        YamlProperties.activeKey = activeKey;
    }
    @Value("${custom.face.type}")
    public void setFaceType(Integer faceType) {
        YamlProperties.faceType = faceType;
    }
*/
    @Value("${custom.fontDynamicCode}")
    public void setFontDynamicCodeSwitch(String fontDynamicCodeSwitch) {
        YamlProperties.fontDynamicCodeSwitch = fontDynamicCodeSwitch;
    }
    }*/
    @Value("${configFile.type}")
    public void setRunModel(Integer runModel) {
        YamlProperties.runModel = runModel;
    }
    @Value("${custom.cors}")
    public void setAllowedCORSDomainList(String allowedCORSDomainList) {
        YamlProperties.allowedCORSDomainList = allowedCORSDomainList;
    /*@Value("${ftpInforMation.ftpIp}")
    public void setFtpIp(String ftpIp){
        YamlProperties.ftpIp=ftpIp;
    }
    @Value("${custom.restartPasswd}")
    public void setRestartPasswd(String restartPasswd) {
        YamlProperties.restartPasswd = restartPasswd;
    @Value("${ftpInforMation.ftpPort}")
    public void setFtpPort(Integer ftpPort){
        YamlProperties.ftpPort=ftpPort;
    }
    @Value("${custom.rsa.publicKeyOld}")
    public void setPublicKeyOld(String publicKeyOld) {
        YamlProperties.publicKeyOld = publicKeyOld;
    @Value("${ftpInforMation.ftpUserName}")
    public void setFtpUserName(String ftpUserName){
        YamlProperties.ftpUserName=ftpUserName;
    }
    @Value("${custom.rsa.privateKeyOld}")
    public void setPrivateKeyOld(String privateKeyOld) {
        YamlProperties.privateKeyOld = privateKeyOld;
    }
    @Value("${ftpInforMation.ftpPassword}")
    public void setFtpPassword(String ftpPassword){
        YamlProperties.ftpPassword=ftpPassword;
    }*/
    @Value("${custom.rsa.publicKey}")
    public void setPublicKey(String publicKey) {
        YamlProperties.publicKey = publicKey;
    }
    @Value("${custom.rsa.privateKey}")
    public void setPrivateKey(String privateKey) {
        YamlProperties.privateKey = privateKey;
    }
    @Value("${custom.aes.defaultKey}")
    public void setAesDefaultKey(String aesDefaultKey) {
        YamlProperties.aesDefaultKey = aesDefaultKey;
    }
    @Value("${custom.aes.iv}")
    public void setAesIv(String aesIv) {
        YamlProperties.aesIv = aesIv;
    }
    @Value("${custom.i18n}")
    public void setI18nLanguage(String i18nLanguage) {
        YamlProperties.i18nLanguage = i18nLanguage;
    }
}
src/main/java/com/whyc/controller/IndexController.java
New file
@@ -0,0 +1,26 @@
package com.whyc.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@Api(tags = "index")
public class IndexController {
    @RequestMapping("/")
    @ApiOperation("默认跳转,无需调用")
    public void index(HttpServletResponse response, HttpServletRequest request){
        try {
            response.sendRedirect("/ms/index.html?n="+System.currentTimeMillis());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
src/main/java/com/whyc/controller/LoginController.java
New file
@@ -0,0 +1,44 @@
package com.whyc.controller;
import com.whyc.dto.Response;
import com.whyc.pojo.UserInf;
import com.whyc.service.UserInfService;
import com.whyc.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RequestMapping("login")
@RestController
@Api(tags = "登录")
public class LoginController {
    @Autowired
    private UserInfService service;
    @PostMapping("login")
    @ApiOperation(value ="登录")
    public Response login(@RequestParam String uname, String usnId, HttpServletRequest request){
        return service.login(uname,usnId,request);
    }
    @ApiOperation(value = "修改密码")
    @GetMapping("changeSnId")
    public Response changeSnId(@RequestParam String oldSnId,@RequestParam String newSnId){
        UserInf uinf= UserUtil.getUser();
        return service.changeSnId(uinf.getUname(),oldSnId,newSnId);
    }
    @PostMapping("logout")
    @ApiOperation(value ="退出登录")
    public void logout(){
        service.logout();
    }
}
src/main/java/com/whyc/controller/OperationLogController.java
New file
@@ -0,0 +1,31 @@
package com.whyc.controller;
import com.whyc.dto.Response;
import com.whyc.pojo.OperationLog;
import com.whyc.service.OperationLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("operationLog")
@Api(tags = "操作日志")
public class OperationLogController {
    @Autowired
    private OperationLogService service;
    @PostMapping("getPage")
    @ApiOperation("分页-查询")
    public Response getPage(@RequestBody OperationLog param){
        return service.getPage(param);
    }
    @GetMapping("getTypes")
    @ApiOperation("事件类型-查询")
    public Response getEnumTypes(){
        return service.getEnumTypes();
    }
}
src/main/java/com/whyc/controller/UserInfController.java
New file
@@ -0,0 +1,65 @@
package com.whyc.controller;
import com.whyc.dto.Response;
import com.whyc.pojo.UserInf;
import com.whyc.service.UserInfService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
@Api(tags = "用户管理")
@RequestMapping("userInf")
public class UserInfController {
    @Autowired
    private UserInfService service;
    @ApiOperation(value = "查询所有用户信息",notes = "排除uid在100以内的(100以内默认是管理员)")
    @GetMapping("getAllUser")
    public Response getAllUser(@RequestParam int pageCurr, @RequestParam int pageSize){
        return service.getAllUser(pageCurr,pageSize);
    }
    @ApiOperation(value = "编辑用户权限和用户名")
    @GetMapping("updateUser")
    public Response updateUser(@RequestParam int uid,@RequestParam(required = false) String uname,@RequestParam(required = false) int udownloadRole){
        return service.updateUser(uid,uname,udownloadRole);
    }
    @ApiOperation(value = "新添加用户信息")
    @PostMapping("addUser")
    public Response addUser(@RequestBody UserInf uinf){
        return service.addUser(uinf);
    }
    @ApiOperation(value = "删除用户信息")
    @GetMapping("deleteUser")
    public Response deleteUser(@RequestParam int uid){
        return service.delUser(uid);
    }
    @ApiOperation(value = "将用户添加至100~1000管理员")
    @GetMapping("improveRole")
    public Response improveRole(@RequestParam int uid){
        return service.improveRole(uid);
    }
    @ApiOperation(value = "将管理员变成普通用户")
    @GetMapping("dropRole")
    public Response dropRole(@RequestParam int uid, HttpServletRequest request){
        return service.dropRole(uid,request);
    }
    @GetMapping("getUserNameList")
    @ApiOperation(tags = "操作日志",value = "操作人姓名-查询-操作日志使用")
    public Response getUserNameList(){
        return service.getUserNameList();
    }
    @GetMapping("resetSnId")
    @ApiOperation(value = "重置密码")
    public Response resetSnId(@RequestParam int uid){
        return service.resetSnId( uid);
    }
}
src/main/java/com/whyc/filter/RolesOrAuthorizationFilter.java
New file
@@ -0,0 +1,36 @@
package com.whyc.filter;
import com.whyc.pojo.UserInf;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.Set;
/**
 * 自定义过滤规则,只需要包含某个角色,就授权
 */
public class RolesOrAuthorizationFilter extends AuthorizationFilter {
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        Subject subject = getSubject(request, response);
        String[] rolesArray = (String[]) mappedValue;
        if (rolesArray == null || rolesArray.length == 0) {
            return true;
        }
        Set<String> roles = CollectionUtils.asSet(rolesArray);
        //判断为or
        UserInf user = (UserInf) subject.getPrincipals().getPrimaryPrincipal();
        for (String role :roles){
            if (subject.hasRole(role)){
                return true;
            }
        }
        return false;
    }
}
src/main/java/com/whyc/mapper/DocUserMapper.java
New file
@@ -0,0 +1,14 @@
package com.whyc.mapper;
import com.whyc.pojo.UserInf;
import java.util.List;
public interface DocUserMapper extends CustomMapper<UserInf>{
    //查询所有用户信息
    List<UserInf> getAllUser(UserInf userInf);
    //查询密码
    String selectSnId(String name);
    //查询所有用户(权限管理用)
    List<UserInf> getAllDocUser();
}
src/main/java/com/whyc/mapper/OperationLogMapper.java
New file
@@ -0,0 +1,7 @@
package com.whyc.mapper;
import com.whyc.mapper.CustomMapper;
import com.whyc.pojo.OperationLog;
public interface OperationLogMapper extends CustomMapper<OperationLog> {
}
src/main/java/com/whyc/mapper/UserInfMapper.java
New file
@@ -0,0 +1,26 @@
package com.whyc.mapper;
import com.whyc.mapper.CustomMapper;
import com.whyc.pojo.UserInf;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserInfMapper extends CustomMapper<UserInf> {
    //查询密码
    String selectSnId(String uname);
    //判断是否存在普通用户(uid>100),若无,初始为1001
    int judgeUname();
    //查询所有用户信息
    List<UserInf> getAllUser();
    //查询100~1000中最大的uid
    String getIn1000();
    //创建100~1000的id表,不存在则创建
    void createNumber();
    //判断表是否存在
    String existTable();
    //插入默认数据
    void setUnumber(@Param("sql") String sql);
    //查询最大的uid
    String getMaxUid();
}
src/main/java/com/whyc/pojo/OperationLog.java
New file
@@ -0,0 +1,39 @@
package com.whyc.pojo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
 * 审计日志/操作日志
 */
@Data
@TableName(schema = "db_user",value = "operation_log")
public class OperationLog {
    private Integer id;
    private Integer userId;
    private String userName;
    private Integer type1;
    private Integer type2;
    private String msg;
    private String detail;
    private String ip;
    private Date createTime;
    @TableField(exist = false)
    private String type1Name;
    @TableField(exist = false)
    private String type2Name;
    @TableField(exist = false)
    private Date startTime;
    @TableField(exist = false)
    private Date endTime;
    @TableField(exist = false)
    private Integer pageNum;
    @TableField(exist = false)
    private Integer pageSize;
}
src/main/java/com/whyc/pojo/UserInf.java
New file
@@ -0,0 +1,46 @@
package com.whyc.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
/**
 * <p>
 *
 * </p>
 *
 * @author lxw
 * @since 2022-07-13
 */
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@TableName(schema = "db_user",value = "user_inf")
@ApiModel(value="User对象", description="")
public class UserInf implements Serializable {
    private static final long serialVersionUID = 1L;
    private int uid;
    @ApiModelProperty(value = "rsa加密密码")
    private String usnid;
    @ApiModelProperty(value = "用户名")
    private String uname;
    @ApiModelProperty(value = "下载权限")
    private int udownloadRole;
    public UserInf(int uid, String uname) {
        this.uid = uid;
        this.uname = uname;
    }
}
src/main/java/com/whyc/properties/LinkProperties.java
New file
@@ -0,0 +1,146 @@
package com.whyc.properties;
import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
/**
 * @Description 有序Properties类
 */
public class LinkProperties extends Properties{
    /** serialVersionUID */
    private static final long serialVersionUID = 7573016303908223266L;
    private List<Object> keyList = new ArrayList<Object>();
    /**
     * 默认构造方法
     */
    public LinkProperties() {
    }
    /**
     * 从指定路径加载信息到Properties
     * @param path
     */
    public LinkProperties(String path) {
        try {
            InputStream is = new FileInputStream(path);
            this.load(is);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException("指定文件不存在!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 重写put方法,按照property的存入顺序保存key到keyList,遇到重复的后者将覆盖前者。
     */
    @Override
    public synchronized Object put(Object key, Object value) {
        this.removeKeyIfExists(key);
        keyList.add(key);
        return super.put(key, value);
    }
    /**
     * 重写remove方法,删除属性时清除keyList中对应的key。
     */
    @Override
    public synchronized Object remove(Object key) {
        this.removeKeyIfExists(key);
        return super.remove(key);
    }
    /**
     * keyList中存在指定的key时则将其删除
     */
    private void removeKeyIfExists(Object key) {
        keyList.remove(key);
    }
    /**
     * 获取Properties中key的有序集合
     * @return
     */
    public List<Object> getKeyList() {
        return keyList;
    }
    /**
     * 保存Properties到指定文件,默认使用UTF-8编码
     * @param path 指定文件路径
     */
    public void store(String path) {
        this.store(path, "UTF-8");
    }
    /**
     * 保存Properties到指定文件,并指定对应存放编码
     * @param path 指定路径
     * @param charset 文件编码
     */
    public void store(String path, String charset) {
        if (path != null && !"".equals(path)) {
            try {
                OutputStream os = new FileOutputStream(path);
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, charset));
                this.store(bw, null);
                bw.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            throw new RuntimeException("存储路径不能为空!");
        }
    }
    /**
     * 重写keys方法,返回根据keyList适配的Enumeration,且保持HashTable keys()方法的原有语义,
     * 每次都调用返回一个新的Enumeration对象,且和之前的不产生冲突
     */
    @Override
    public synchronized Enumeration<Object> keys() {
        return new EnumerationAdapter<Object>(keyList);
    }
    /**
     * List到Enumeration的适配器
     */
    private class EnumerationAdapter<T> implements Enumeration<T> {
        private int index = 0;
        private final List<T> list;
        private final boolean isEmpty;
        public EnumerationAdapter(List<T> list) {
            this.list = list;
            this.isEmpty = list.isEmpty();
        }
        public boolean hasMoreElements() {
            //isEmpty的引入是为了更贴近HashTable原有的语义,在HashTable中添加元素前调用其keys()方法获得一个Enumeration的引用,
            //之后往HashTable中添加数据后,调用之前获取到的Enumeration的hasMoreElements()将返回false,但如果此时重新获取一个
            //Enumeration的引用,则新Enumeration的hasMoreElements()将返回true,而且之后对HashTable数据的增、删、改都是可以在
            //nextElement中获取到的。
            return !isEmpty && index < list.size();
        }
        public T nextElement() {
            if (this.hasMoreElements()) {
                return list.get(index++);
            }
            return null;
        }
    }
}
src/main/java/com/whyc/properties/PropertiesUtil.java
New file
@@ -0,0 +1,38 @@
package com.whyc.properties;
import lombok.extern.log4j.Log4j2;
/**
 * @Description 读取Properties的工具类
 */
@Log4j2
public class PropertiesUtil {
    public static LinkProperties propertiesShiro = new LinkProperties();
    /**
     * 读取properties配置文件信息
     */
    static {
        /*String sysName = System.getProperty("sys.name");
        if (StringUtils.isEmpty(sysName)) {
            sysName = "application.properties";
        } else {
            sysName += ".properties";
        }*/
        try {
            propertiesShiro.load(PropertiesUtil.class.getClassLoader()
                    .getResourceAsStream("config/authentication.properties"));
        } catch (Exception e) {
            log.warn("资源路径中不存在authentication.properties权限文件,忽略读取!");
        }
    }
    /**
     * 根据key得到value的值
     */
    public static String getShiroValue(String key) {
        return propertiesShiro.getProperty(key);
    }
}
src/main/java/com/whyc/realm/CustomRealm.java
New file
@@ -0,0 +1,55 @@
package com.whyc.realm;
import com.whyc.anotation.Realm;
import com.whyc.pojo.UserInf;
import com.whyc.service.UserBridgeService;
import com.whyc.util.RSAUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
/**
 * 实际处理认证授权,跟数据库交互
 */
@Realm
public class CustomRealm extends AuthorizingRealm {
    /**必须@Lazy注解,@Lazy与@Autowired组合,使得依赖于Service相关的Bean都是lazy-resolution proxy*/
    @Lazy
    @Autowired
    UserBridgeService userBridgeService;
    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String userName = (String) authenticationToken.getPrincipal();
        UserInf user = userBridgeService.findPasswordByUserName(userName);
        if(user.getUid()==0){
            throw new UnknownAccountException("账号不存在");
        }
        String password = RSAUtil.decrypt(user.getUsnid(),RSAUtil.getPrivateKey());
        return new SimpleAuthenticationInfo(user,password,getName());
    }
    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        UserInf user = (UserInf) principalCollection.getPrimaryPrincipal();
        return userBridgeService.getAuthorizationInfo(user);
    }
    /**加密*//*
    @PostConstruct
    public void initCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(SuperConstant.HASH_ALGORITHM_MD5);
        matcher.setHashIterations(SuperConstant.HASH_INTEGRATIONS_ONE);
        setCredentialsMatcher(matcher);
    }*/
}
src/main/java/com/whyc/service/OperationLogService.java
New file
@@ -0,0 +1,136 @@
package com.whyc.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whyc.constant.OperationLogEnum;
import com.whyc.dto.Response;
import com.whyc.mapper.OperationLogMapper;
import com.whyc.pojo.OperationLog;
import com.whyc.pojo.UserInf;
import com.whyc.util.HttpUtil;
import com.whyc.util.UserUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
@Service
public class OperationLogService {
    @Resource
    private OperationLogMapper mapper;
    public void record(Integer type1, Integer type2, String msg, String detail) {
        OperationLog log = new OperationLog();
        UserInf user = UserUtil.getUser();
        log.setUserId(user.getUid());
        log.setUserName(user.getUname());
        log.setType1(type1);
        log.setType2(type2);
        log.setMsg(msg);
        log.setDetail(detail);
        log.setIp(HttpUtil.getRequest().getRemoteAddr());
        log.setCreateTime(new Date());
        mapper.insert(log);
    }
    public void record(Integer type1, Integer type2, String msg, String detail,String remoteIp) {
        OperationLog log = new OperationLog();
        UserInf user = UserUtil.getUser();
        log.setUserId(user.getUid());
        log.setUserName(user.getUname());
        log.setType1(type1);
        log.setType2(type2);
        log.setMsg(msg);
        log.setDetail(detail);
        log.setIp(remoteIp);
        log.setCreateTime(new Date());
        mapper.insert(log);
    }
    public Response getEnumTypes() {
        Map<OperationLog, List<OperationLog>> map = new HashMap<>();
        OperationLogEnum[] instances = OperationLogEnum.values();
        for (OperationLogEnum instance : instances) {
            Set<OperationLog> type1Logs = map.keySet();
            //两位数为一级,非两位数为二级
            Integer type = instance.getType();
            String name = instance.getName();
            if(type.toString().length() == 2){ //一级
                OperationLog log = new OperationLog();
                log.setType1(type);
                log.setType1Name(name);
                map.put(log,new LinkedList<>());
            }else{ //二级
                for (OperationLog type1Log : type1Logs) {
                    if(type.toString().startsWith(type1Log.getType1().toString())){
                        List<OperationLog> type2Logs = map.get(type1Log);
                        OperationLog type2Log = new OperationLog();
                        type2Log.setType2(type);
                        type2Log.setType2Name(name);
                        type2Logs.add(type2Log);
                    }
                }
            }
        }
        return new Response().set(1,map);
    }
    public Response getPage(OperationLog param) {
        Integer pageNum = param.getPageNum();
        Integer pageSize = param.getPageSize();
        PageHelper.startPage(pageNum,pageSize);
        QueryWrapper<OperationLog> query = Wrappers.query();
        if(param.getUserName() != null){
            query.eq("user_name",param.getUserName());
        }
        if(param.getType1() != null){
            query.eq("type1",param.getType1());
        }
        if(param.getType2() != null){
            query.eq("type2",param.getType2());
        }
        if(param.getStartTime() != null) {
            query.ge("create_time", param.getStartTime());
        }
        if(param.getEndTime() != null) {
            query.le("create_time", param.getEndTime());
        }
        query.orderByDesc("id");
        List<OperationLog> operationLogs = mapper.selectList(query);
        injectTypeName(operationLogs);
        PageInfo<OperationLog> pageInfo = new PageInfo<>(operationLogs);
        return new Response().set(1,pageInfo);
    }
    /**注入type值对应的name*/
    private void injectTypeName(List<OperationLog> operationLogs) {
        for (OperationLog log : operationLogs) {
            Integer type1 = log.getType1();
            Integer type2 = log.getType2();
            Map<OperationLog, List<OperationLog>> logConstantMap = (Map<OperationLog, List<OperationLog>>) getEnumTypes().getData();
            Set<OperationLog> type1Set = logConstantMap.keySet();
            for (OperationLog temp : type1Set) {
                if(type1 == temp.getType1().intValue()){
                    //注入type1事件类型
                    log.setType1Name(temp.getType1Name());
                    //注入type2事件类型
                    List<OperationLog> type2List = logConstantMap.get(temp);
                    for (OperationLog temp2 : type2List) {
                        if(type2 == temp2.getType2().intValue()){
                            log.setType2Name(temp2.getType2Name());
                            break;
                        }
                    }
                    break;
                }
            }
        }
    }
}
src/main/java/com/whyc/service/UserBridgeService.java
New file
@@ -0,0 +1,76 @@
package com.whyc.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.whyc.mapper.DocUserMapper;
import com.whyc.pojo.UserInf;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
 * 处理 shiro认证,授权,和数据库交互
 */
@Service
//Unified Naming
//@CacheConfig(cacheNames ={"userBridge"})
@DependsOn("caffeineCacheManager")
public class UserBridgeService {
    @Resource
    private DocUserMapper userMapper;
    @Resource
    private CacheManager caffeineCacheManager;
    public UserInf findPasswordByUserName(String userName) {
        UserInf userInf = null;
        QueryWrapper<UserInf> queryWrapper = Wrappers.query();
        queryWrapper.select("uid","uname","usnid","udownload_role").eq("uname",userName);
        userInf = userMapper.selectOne(queryWrapper);
        return userInf==null?new UserInf(0,"用户不存在"):userInf;
    }
/*    public UserInf findUserByMobilephone(String mobilephone){
        QueryWrapper<UserInf> queryWrapper = Wrappers.query();
        queryWrapper.select("uId","uName","upassword","UKey_ID","uRole","uMobilephone").eq("uMobilephone",mobilephone);
        List<UserInf> list = userMapper.selectList(queryWrapper);
        return list.size()==0?new UserInf(0,"用户不存在"):list.get(0);
    }*/
    /**
     * TODO 采用caffeineCache重写
     * @param user
     * @return
     */
    //@Cacheable(key = "#root.methodName+#p0.id")
    public AuthorizationInfo getAuthorizationInfo(UserInf user) {
        System.out.println("=========执行了UserBridgeService.getAuthorization方法==========");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        /*//添加Roles和Permissions
        List<String> roles = findRolesByUserId(user.getId());
        List<String> perms = findPermissionsByUserId(user.getId());
        authorizationInfo.addRoles(roles);
        authorizationInfo.addStringPermissions(perms);*/
        return authorizationInfo;
    }
    private List<String> findPermissionsByUserId(Long userId) {
       /* List<String> perms = rolePermissionMapper.findPermissionsByUserId(userId);
        return perms;*/
       return null;
    }
    private List<String> findRolesByUserId(Long userId) {
        //List<String> roles =userRoleMapper.findRolesByUserId(userId);
        //roles.add("dev");
        return null;
    }
}
src/main/java/com/whyc/service/UserInfService.java
New file
@@ -0,0 +1,227 @@
package com.whyc.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whyc.dto.Response;
import com.whyc.mapper.UserInfMapper;
import com.whyc.pojo.UserInf;
import com.whyc.util.MD5Util;
import com.whyc.util.RSAUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class UserInfService {
    @Autowired(required = false)
    private UserInfMapper mapper;
    //查询所有用户信息
    public Response getAllUser( int pageCurr, int pageSize) {
        PageHelper.startPage(pageCurr,pageSize);
        List<UserInf> list=mapper.getAllUser();
        PageInfo pageInfo=new PageInfo(list);
        return new Response().setII(1,list!=null,pageInfo,"数据返回");
    }
    //编辑权限
    public Response updateUser(int uid,String uname, int udownloadRole) {
        UpdateWrapper wrapper=new UpdateWrapper();
        wrapper.set("udownload_role",udownloadRole);
        if(uname!=null){
            wrapper.set("uname",uname);
        }
        wrapper.eq("uid",uid);
        int bl=mapper.update(null,wrapper);
        return new Response().set(1,bl>0);
    }
    //新添加用户信息
    public Response addUser(UserInf uinf) {
        QueryWrapper wrapper=new QueryWrapper();
        //判断是否存在普通用户(uid>100),若无,初始为1001
        int judgecount=mapper.judgeUname();
        if(judgecount==0){
            uinf.setUid(101);
        }
        String pwd= RSAUtil.encrypt("123456", RSAUtil.getPublicKey());
        uinf.setUsnid(pwd);
        wrapper.eq("uname",uinf.getUname());
        List list=mapper.selectList(wrapper);
        if(list!=null&&list.size()>0){
            return new Response().setII(1,false,list,"用户名已存在");
        }
        int bl=mapper.insert(uinf);
        return new Response().set(1,bl>0);
    }
    //修改密码
    public Response changeSnId(String uname,String oldSnId, String newSnId) {
        if(uname==null||uname.equals("")){
            return new Response().set(1,false,"找不到用户");
        }
        //验证老密码是否正确
        String snIdRsa=mapper.selectSnId(uname);
        //解密
        String snId=RSAUtil.decrypt(snIdRsa,RSAUtil.getPrivateKey());
        String[] decOld=RSAUtil.decryptFrontP(oldSnId,RSAUtil.fontSeparator);
        String oldId=decOld[0];
        String[] newOld=RSAUtil.decryptFrontP(newSnId,RSAUtil.fontSeparator);
        String newId=newOld[0];
        if(oldId.equals(snId)){
            UpdateWrapper wrapper=new UpdateWrapper();
            wrapper.set("usnid",RSAUtil.encrypt(newId,RSAUtil.getPublicKey()));
            wrapper.eq("uname",uname);
            int flag=mapper.update(null,wrapper);
            return  new Response().set(1,flag>0,flag>0?"修改成功":"修改失败");
        }else {
            return new Response().set(1,false,"原密码不正确");
        }
    }
    //重置密码
    public Response resetSnId(int uid ) {
        UpdateWrapper wrapper=new UpdateWrapper();
        wrapper.set("usnid",RSAUtil.encrypt("123456",RSAUtil.getPublicKey()));
        wrapper.eq("uid",uid);
        int flag=mapper.update(null,wrapper);
        return  new Response().set(1,flag>0,flag>0?"修改成功":"修改失败");
    }
    //删除用户信息
    public Response delUser(int uid) {
        UpdateWrapper wrapper=new UpdateWrapper();
        wrapper.eq("uid",uid);
        int bl=mapper.delete(wrapper);
        return new Response().setII(1,bl>0,bl,"删除返回");
    }
    public Response login(String uname, String usnId, HttpServletRequest request) {
        Response response = new Response();
        String[] dataArr = RSAUtil.decryptFrontP(usnId, RSAUtil.fontSeparator);
        //验签md5
        if(dataArr[0]==null||dataArr[1]==null){
            return response.set(1, false, "密码验签失败");
        }
        if (!dataArr[1].equals(MD5Util.encryptMD5(org.apache.commons.lang3.StringUtils.trim(dataArr[0])))) {
            return response.set(1, false, "密码验签失败");
        }
        UsernamePasswordToken userToken = new UsernamePasswordToken(uname, dataArr[0]);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(userToken);
        } catch (Exception e) {
            if(e instanceof UnknownAccountException){
                return response.set(1,false,"账号不存在");
            }
            return response.set(1,false,"密码错误");
        }
        //登录成功
        ServletContext servletContext = request.getServletContext();
        servletContext.setAttribute(uname, request.getSession().getId());
        //Session存储当前用户及权限组列表
        UserInf userDB = (UserInf) subject.getPrincipal();
        userDB.setUsnid(null);
        request.getSession().setAttribute("user", userDB);
        return response.setII(1,true, userDB,"登录成功");
    }
    public void logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
    }
    //将用户添加至100~1000管理员
    public Response improveRole(int uid) {
        //判断表是否存在
        String tableName = mapper.existTable();
        if(tableName==null){
            ///创建100~1000的id表,不存在则创建
            mapper.createNumber();
            //插入默认数据
            String sql=" INSERT INTO db_user.temp_numbers(unumber) " +
                    " VALUES ";
            for(int i=101;i<=1000;i++){
                sql+="("+i+")";
                if(i!=1000){
                    sql+=",";
                }
            }
            mapper.setUnumber(sql);
        }
        String minUid=mapper.getIn1000();
        if(minUid==null){
            return new Response().set(1,false,"管理员个数超过上限");
        }
        UpdateWrapper wrapper =new UpdateWrapper();
        wrapper.set("uid",Integer.valueOf(minUid));
        wrapper.eq("uid",Integer.valueOf(uid));
        int flag= mapper.update(null,wrapper);
        return new Response().set(1,flag>0,flag>0?"身份变更成功":"身份变更失败");
    }
    //将管理员变成普通用户
    public Response dropRole(int uid, HttpServletRequest request) {
        //查询最大的uid
        String maxUid=mapper.getMaxUid();
        if(maxUid==null){
            maxUid="1001";
        }
        //根据用户id查询用户信息
        QueryWrapper qWrapper=new QueryWrapper();
        qWrapper.eq("uid",uid);
        qWrapper.last("limit 1");
        UserInf uinf=mapper.selectOne(qWrapper);
        //编辑
        UpdateWrapper wrapper =new UpdateWrapper();
        wrapper.set("uid",Integer.valueOf(maxUid)+1);
        wrapper.eq("uid",uid);
        int flag= mapper.update(null,wrapper);
        //如果是普通用户自己强退,将用户名对应的sessionId变更
        ServletContext servletContext = request.getServletContext();
        servletContext.setAttribute(uinf.getUname(),"123456");
        return new Response().set(1,flag>0,flag>0?"身份变更成功":"身份变更失败");
    }
    public Response getUserNameList() {
        QueryWrapper<UserInf> query = Wrappers.query();
        query.select("uname");
        List<String> userNameList = mapper.selectList(query).stream().map(UserInf::getUname).collect(Collectors.toList());
        return new Response().set(1,userNameList);
    }
    //登录检测
    public Response checkUserWebSocket(HttpSession httpSession){
        Response model = new Response();
        try {
            UserInf user = (UserInf) httpSession.getAttribute("user");
            if(user!=null){
                String sessionId = (String) httpSession.getServletContext().getAttribute(user.getUname());
                if(httpSession.getId().equals(sessionId)){
                    model.set(1,user,null);
                }else{
                    if(sessionId.equals("123456")){
                        model.set(1,false,"身份权限变更,请重新登录");
                    }else{
                        model.set(1,false,"不同主机登录");
                    }
                    //用户在其他主机登录,强迫用户在本机的session失效
                    httpSession.invalidate();
                }
            }
            else {
                model.set(1,false,"用户信息失效,请重新登录");
            }
        }catch (Exception e){
            model.set(1,false,"登录信息失效,重新登录");
        }
        return model;
    }
}
src/main/java/com/whyc/util/HttpUtil.java
New file
@@ -0,0 +1,97 @@
package com.whyc.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HttpUtil {
    /*
     * 获取HttpServletRequest
     */
    public static HttpServletRequest getRequest(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        return request;
    }
    /*
     * 获取HttpServletResponse
     */
    public static HttpServletResponse getResponse(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = requestAttributes.getResponse();
        return response;
    }
    /*
     * 获取HttpSession
     */
    public static HttpSession getSession(){
        return getRequest().getSession();
    }
    /**
     *
     * @return    返回application
     */
    public static ServletContext getApplication(){
        return getSession().getServletContext();
    }
    /*
     * 获取将对象转换成json格式
     */
    public static String toJson(Object obj){
        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
        return gson.toJson(obj);
    }
    public static String chageDateToString(Date time,String type){
        String msg = "";
        SimpleDateFormat sdf = new SimpleDateFormat(type);
        msg = sdf.format(time);
        return msg;
    }
    /**
     *
     * @param datetype    需要解析的日期的格式如:"yyyy-MM-dd HH:mm:ss"
     * @return    得到对应的gson对象
     */
    public static Gson getGson(String datetype){
        return new  GsonBuilder().setDateFormat(datetype).create();
    }
    /**
     * 获取默认的gson对象
     * @return
     */
    public static Gson getGson(){
        return new Gson();
    }
    public static <T> T getObject(String jsonstring,Type listtype){
        Gson gson=new Gson();
        T t=null;
        try {
            t=gson.fromJson(jsonstring, listtype);
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
        }
        return t;
    }
}
src/main/java/com/whyc/util/JasyptUtils.java
New file
@@ -0,0 +1,69 @@
package com.whyc.util;
import lombok.extern.slf4j.Slf4j;
import org.jasypt.properties.PropertyValueEncryptionUtils;
import org.jasypt.util.text.BasicTextEncryptor;
import java.util.Objects;
@Slf4j
public final class JasyptUtils {
    public static void main(String[] args) {
        //String a = encrypt("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");
        //String a = encrypt("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KFXt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAPvTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZstiIBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7NbAUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==");
        String a = encrypt("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdHXXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB");
        decrypt(a);
    }
    /**
     * 加密使用密钥
     */
    //private static final String PRIVATE_KEY = "hELEEWWEEr9Lu6HgEvttjj8vYhy3ID+PqPbumuXhcHhe";
    private static BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();
    static {
        basicTextEncryptor.setPassword(Objects.requireNonNull(RSAUtil.decrypt("DF3lSrjXSHClZgQzagH0D038z1gCoG+FcZLPMZ93Ucz1MeNCN+J5iawqQKzMXusXPuHeygfuLSajiCNi8ad2F7H7lpL9FhzjH+2Q9d9d1H2xRe+ElHh0SC8aT4FHgrazhx73wn2MlxX8SIm2PvC8oBLXbM+7KQ4r5bNwiQl0uUOC7D9ONbYzQAy8zCkCBke+h4Q6b5SlGaGz2OswKJPe7Wjpsf/3hnUKV6KP+ACYfFry9Nq13Wb3nsPfjuMnwsmUe8sRxj77pIVmrbEIMaO12GJMJbErA0/1ZjfPkzH3YFZe/mmSOmHegM/jiXnnPemh+LRyZGrKF3Y19B8Cl1EMxp106ss8/7ypYiFn0XWb7gRQqfuqQ8zsU0lOWxCWuk2jyWKxBdftt3edDzmoROHJfllHRffgPZ/MPYg6C6JqBXz7Xqngb0mClwt7OQVSvTau+NdTlMoYdcULOTZqa8IJi4rtUMMnVdhj0Avpl6ekXBPeVcvWsqTpGoep5T0yQJ9M")));
    }
    /**
     * 私有构造方法,防止被意外实例化
     */
    private JasyptUtils() {
    }
    /**
     * 明文加密
     *
     * @param plaintext 明文
     * @return String
     */
    public static String encrypt(String plaintext) {
        log.info("明文字符串为:{}", plaintext);
        // 使用的加密算法参考2.2节内容,也可以在源码的类注释中看到
        String ciphertext = basicTextEncryptor.encrypt(plaintext);
        log.info("密文字符串为:{}", ciphertext);
        return ciphertext;
    }
    /**
     * 解密
     *
     * @param ciphertext 密文
     * @return String
     */
    public static String decrypt(String ciphertext) {
        log.info("密文字符串为:{}", ciphertext);
        ciphertext = "ENC(" + ciphertext + ")";
        if (PropertyValueEncryptionUtils.isEncryptedValue(ciphertext)) {
            String plaintext = PropertyValueEncryptionUtils.decrypt(ciphertext, basicTextEncryptor);
            log.info("明文字符串为:{}", plaintext);
            return plaintext;
        }
        log.error("解密失败!");
        return "";
    }
}
src/main/java/com/whyc/util/MD5Util.java
New file
@@ -0,0 +1,47 @@
package com.whyc.util;
import org.apache.commons.codec.digest.DigestUtils;
public class MD5Util {
    /**加密*/
    public static String encryptMD5(String data){
        String result=null;
        if(data!=null && data.length()>0){
            result= DigestUtils.md5Hex(data);
        }
        return result;
    }
    /**
     * 使用timestamp+盐方式,进行签名验证
     * 当前时间戳为13位数
     */
    public static boolean checkSignMD5(String time,String randomStr,String sign){
        String usefulNum = randomStr;
        //加盐方式,根据末尾的值进行不同的加密规则
        char lastChar = time.charAt(12);
        int lastNum = Integer.parseInt(String.valueOf(lastChar));
        switch (lastNum){
            //在第一位加字符串 rd@c3doed
            case 0: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3dozero");break;
            case 1: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doenoe");break;
            case 2: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doktwo");break;
            case 3: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3dolthree");break;
            case 4: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doexfour");break;
            case 5: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doedefive");break;
            case 6: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doedhsix");break;
            case 7: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doedtseven");break;
            case 8: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doedbeight");break;
            case 9: usefulNum += time.replace(String.valueOf(lastChar),"rd@c3doedrnine");break;
        }
        //MD5加密后
        String signNow = encryptMD5(usefulNum);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(signNow.charAt(i * 2));
        }
        String signResult = sb.append(signNow).toString();
        return sign.equals(signResult);
    }
}
src/main/java/com/whyc/util/RSAUtil.java
New file
@@ -0,0 +1,280 @@
package com.whyc.util;
import com.whyc.constant.YamlProperties;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.LinkedList;
import java.util.List;
public class RSAUtil {
    /**
     * 固定公私钥
     */
    private static final  String publicKey = YamlProperties.publicKey;
    private static final  String privateKey = YamlProperties.privateKey;
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 384;
    public static final String fontSeparator = "&&&&&&&&&&";
    /**
     * 获取密钥对
     *
     * @return 密钥对
     */
    public static List<String> getKeyPair() throws Exception {
        LinkedList<String> list = new LinkedList<>();
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(3072);
        KeyPair keyPair = generator.generateKeyPair();
        String publicKey = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
        String privateKey = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());
        System.out.println("公钥:"+publicKey);
        System.out.println("私钥:"+privateKey);
        list.add(publicKey);
        list.add(privateKey);
        return list;
    }
    /**
     * 获取私钥
     *
     * @param privateKey 私钥字符串
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) {
        try {
            KeyFactory keyFactory = null;
            keyFactory = KeyFactory.getInstance("RSA");
            byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
            return keyFactory.generatePrivate(keySpec);
        }catch (NoSuchAlgorithmException | InvalidKeySpecException e){
            return null;
        }
    }
    /**
     * 获取私钥
     *
     * @return
     */
    public static PrivateKey getPrivateKey() {
        try {
            KeyFactory keyFactory = null;
            keyFactory = KeyFactory.getInstance("RSA");
            byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
            return keyFactory.generatePrivate(keySpec);
        }catch (NoSuchAlgorithmException | InvalidKeySpecException e){
            return null;
        }
    }
    /**
     * 获取公钥
     *
     * @param publicKey 公钥字符串
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        return keyFactory.generatePublic(keySpec);
    }
    /**
     * 获取公钥
     *
     * @return
     */
    public static PublicKey getPublicKey(){
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
            return keyFactory.generatePublic(keySpec);
        }catch (Exception e){
            return null;
        }
    }
    /**
     * RSA加密
     *
     * @param data 待加密数据
     * @param publicKey 公钥
     * @return
     */
    public static String encrypt(String data, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            int inputLen = data.getBytes().length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offset = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offset > 0) {
                if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] encryptedData = out.toByteArray();
            out.close();
            // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
            // 加密后的字符串
            return new String(Base64.encodeBase64String(encryptedData));
        }catch (Exception e){
            return null;
        }
    }
    /**
     * RSA解密
     *
     * @param data 待解密数据
     * @param privateKey 私钥
     * @return
     */
    public static String decrypt(String data, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] dataBytes = Base64.decodeBase64(data);
            int inputLen = dataBytes.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offset = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offset > 0) {
                if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            // 解密后的内容
            return new String(decryptedData, "UTF-8");
        }catch (Exception e){
            return null;
        }
    }
    /**
     * RSA解密
     *
     * @param data 待解密数据
     * @return
     */
    public static String decrypt(String data) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
            byte[] dataBytes = Base64.decodeBase64(data);
            int inputLen = dataBytes.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offset = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offset > 0) {
                if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
                }
                out.write(cache, 0, cache.length);
                i++;
                offset = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            // 解密后的内容
            return new String(decryptedData, "UTF-8");
        }catch (Exception e){
            return null;
        }
    }
    /**
     * 前端加密数据RSA[明文+MD5(明文)]解密为明文和MD5[明文]
     * @param frontEncryptData
     * @return
     */
    public static String[] decryptFront(String frontEncryptData,String separatorStr){
        String[] dataArr = new String[2];
        String dataMD5Mix = RSAUtil.decrypt(frontEncryptData, RSAUtil.getPrivateKey());
        int index = dataMD5Mix.lastIndexOf(separatorStr);
        String data = dataMD5Mix.substring(0, index);
        String dataMD5 = dataMD5Mix.substring(index+separatorStr.length());
        dataArr[0] = data;
        dataArr[1] = dataMD5;
        return dataArr;
    }
    /**
     * 先URL解码,再进行密文解析[rsa(明文+md5)]
     */
    public static String[] decryptFrontP(String frontEncryptData,String separatorStr){
        try {
            frontEncryptData = URLDecoder.decode(frontEncryptData, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String[] dataArr = new String[2];
        String dataMD5Mix = RSAUtil.decrypt(frontEncryptData, RSAUtil.getPrivateKey());
        if(dataMD5Mix!=null){
            int index = dataMD5Mix.lastIndexOf(separatorStr);
            String data = dataMD5Mix.substring(0, index);
            String dataMD5 = dataMD5Mix.substring(index+separatorStr.length());
            dataArr[0] = data;
            dataArr[1] = dataMD5;
        }
        return dataArr;
    }
    public static void main(String[] args) {
        try {
            //String word = "123456";
            //String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdHXXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB";
            //String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KFXt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAPvTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZstiIBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7NbAUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==";
            //List<String> keyPair = getKeyPair();
            //String encryptWord = encrypt(word, getPublicKey(keyPair.get(0)));
            //System.out.println("加密后的字符串:"+encryptWord);
            //String encryptWord = "NTDEt29l3QqDjgbK5AToix14GQNMi2qPDgsIy7JQf0586wEhOr6LgQ3YuZo9gEYLgmRxdOtxTcVCMugIJnXr6xukoopYfdH7epnQlszMYcM73a7mOrI1DJQA8%2B7AnMkm0s3X3GR7CdpT2OHrdogOAywFWhBirETaeY36ZH%2FOrXQ%3D";
            //encryptWord=URLDecoder.decode(encryptWord, "utf-8");
            String encrypt = encrypt("hELEEWWEEr9Lu6HgEvttjj8vYhy3ID+PqPbumuXhcHhe", getPublicKey());
            System.out.println(encrypt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
src/main/java/com/whyc/util/UserUtil.java
New file
@@ -0,0 +1,25 @@
package com.whyc.util;
import com.whyc.pojo.UserInf;
import org.apache.shiro.SecurityUtils;
/**
 * 从Shiro中直接获取用户信息
 */
public class UserUtil {
    public static UserInf getUser(){
        UserInf principal = (UserInf) SecurityUtils.getSubject().getPrincipal();
        if(principal == null){
            UserInf user = new UserInf();
            user.setUname("unlogged user");
            user.setUid(0);
            user.setUdownloadRole(0);
            return user;
        }else {
            return principal;
        }
    }
}
src/main/java/com/whyc/webSocket/LoginCheckSocket.java
New file
@@ -0,0 +1,92 @@
package com.whyc.webSocket;
import com.whyc.config.WebSocketConfig;
import com.whyc.dto.Response;
import com.whyc.service.UserInfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
 * 账号重复登录检查
 */
@Component
@ServerEndpoint(value = "/loginCheck",encoders = WebSocketEncoder.class,configurator = WebSocketConfig.class)
public class LoginCheckSocket {
    private Session session;
    private Thread thread;
    private static UserInfService uinfService;
    @Autowired
    public void setLoginService(UserInfService uinfService) {
        LoginCheckSocket.uinfService = uinfService;
    }
    @OnOpen
    public void onOpen(Session session, EndpointConfig config){
        this.session = session;
        HttpSession httpSession = (HttpSession) config.getUserProperties().get("httpSession");
        if(httpSession == null){
            Map<String, Response> res = new HashMap<>();
            Response resp1 = new Response().set(1, false, "登录信息失效,重新登录");
            res.put("checkLogin", resp1);
            try {
                session.getBasicRemote().sendObject(new Response().set(1,res));
            } catch (IOException | EncodeException e) {
                e.printStackTrace();
            }
        }else {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    try {
                        Map<String, Response> res = new HashMap<>();
                        Response sessionRes = new Response().set(1, httpSession.getId());
                        while (!currentThread().isInterrupted()) {
                            Response response = uinfService.checkUserWebSocket(httpSession);
                            res.put("checkLogin", response);
                            res.put("session", sessionRes);
                            session.getBasicRemote().sendObject(new Response().set(1, res));
                            if (response.getData() instanceof Boolean) {
                                if(response.getData().equals(false)) {
                                    this.interrupt();
                                }
                            }
                            sleep(4000);
                        }
                    } catch (Exception e) {
                        this.interrupt();
                    }
                }
            };
            thread.start();
            this.thread = thread;
        }
    }
    @OnClose
    public void onClose(CloseReason closeReason) throws IOException {
        System.err.println("closeReason = " + closeReason);
        if(session.isOpen()){
            session.close();
        }
    }
    @OnError
    public void onError(Throwable error) throws IOException {
        error.printStackTrace();
        thread.isInterrupted();
        if(session.isOpen()){
            session.close();
        }
    }
}
src/main/resources/config/application-dev.yml
@@ -74,6 +74,11 @@
  community: public
  retries: 1
  timeout: 5000
jasypt:
  encryptor:
    password: hELEEWWEEr9Lu6HgEvttjj8vYhy3ID+PqPbumuXhcHhe
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator
custom:
  #登录验证码 on/off
  fontDynamicCode: on
@@ -82,10 +87,10 @@
  #重启密码
  restartPasswd: ENC(AKxTGQo6bAABeC62B8Dtxw==)
  rsa:
    publicKeyOld: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdHXXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB
    privateKeyOld: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KFXt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAPvTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZstiIBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7NbAUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==
    publicKey: MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu7CdCMIoWXUX584JpmE1bTE1r1MtmZGswsSbsm4s9zqETQ4BmUT2kz/wvvGsI8T3ZvTT4KIyKP4Ez+yNVejMM5XwR95KF4e3UwMc724buWKl4pVL09kvkCZt8ZKf359VAvhyHHz80wIiVmJs6xbho7OBsv/s7Hwho0n4HPL4u/eNR5vWa2rtgQG1+fi1XP0UiSRKKW15Va9R2CI3zB+sffquhyX5fi+06NibWzk7OPU+EGvAwkaJtrmfLAvpwr4+G0MBLIsPVFV17Sgpoj62rtfbhHwmLSo1JTw+/JskDQOjxXfw+w3uHAZgPTlEmn2Ya9ssIljqCBfvM9nbGUWcnmppKlPm6kECa4RsgPiRgPFV+nT/Q98kfUTb798Sy63x4NIZkLQn1DDbmcAgUqLR6y1r0fD8Ne3vVtuZlVR/8ZlcRAfb+th2cNN0rytrnUreJo7kPtTFdkNtmj0KdUkRO8ea0YymEQal+b0tCl3V8osSy+qO2OVRd7yCvpOWEYOBAgMBAAE=
    privateKey: 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
    #publicKeyOld: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdHXXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB
    #privateKeyOld: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KFXt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAPvTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZstiIBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7NbAUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==
    publicKey: ENC(QR8EpIC0jzG2E29Dhtq/vqrwt99WtUix/h2J8OvD90w0fosfUM1EFpdHJ2nsdP84BOeVNoPmudqXCYWVeCuTrVkqfb2z8mMLDl8cry78P8Tu4il3m9hGxqjdeNJbdYA6z6eRaInoJj5BHUyNpAJDaNacMZoOUJU6lMySwujyrD8PfSY97St0XPL5GIFP9rP1FCnlVWBeH4tqZKZ6MGncYJaITUZ/BIPkhpDYxi+i4CnMIBqytCJ6OJCzjLBI44UsQOzsdLgppAE2O0fmgyXA6bh0VRdIaRhqDIrjur2e4sOEvjadORN0Kg==)
    privateKey: ENC(fDshYRxHSlpJ2v+CmDGzH/PlFIKr9+hcPg0patE+nOFMKQaEVNLj9XxOlGEDFabSLFvy1imSRmOF08EE/z9cmlsp+hfbF6feR6YABRHgDxOGWusZ9QKYLhv6vDD6pebKb2W3FCuIHnLicMiJfzpM5KGylTMv7rvtM7tFR8ZhDzn3s8uYotz6ORcfCPdgOcUcNHXT0WS2KA0NigsRH5YMF5IOCP2jNTaOFDDXYacjfGOwjFIGE71BMJCnMRp6RnukbAY1ZN3J88GpYRzYCYD/S9DbGFVY9giH0T7FZs5cgPsCoDZ1dIeJhmjbOxoQpwKoDZzvlYbsstMH+6wApaWgx9TJfBoNjEJdqM1S3asukV4bUq4cZnmryCeSWSYkR2FDuH792rXL3Msh2Jc2hB2Cg9ZPB5hljN5GWV0fYiKNjJW2ovgBZZRWURorkrfBReKsxuLcHlbBcdHBF9DZDJyy40fg9GP6w40uG3hBKd/OlA9IYWNWEgqgeMkNmesG9RTc4X7EG2Ar4MEDa1p6o3unIve/zTCpLoFzKCRIjYcqlW1pZfSwZD4wu6JJf+5tUoXaEEf5YD4dcWCD4DzUcv4qhOpHXDBtM3E45VdacMWZNdE7fXcDzWpgYdUSQ88HsXRjmaW0O/x5irdN5KGa89yj5bDYQeMzR7Cervxml3MUZSrkHVKsa9yWverlLaRXzTue3+MXgDudm1stHju5p2x55GWG9ZfcErDoTNqhgPwcbJnW7/vXFpoTt6AF3t8vbD7f5G+FXnvYLDUWtdNS8KN6X+EOkh4GWootC+QMEKArDr8AyL+5D2TkBGIDMAag/LVwAKSwvBs2+e/xsSlw+AuAsWcfb9whJCZNVogpA1jE56SIdIBtw4G4Lw9LMlJ2MprkV6e2VAtBwpou3fd5pUsKpu51WBfISRy60vls7Fu0mQXrT7cCzThptrk9KgIhjMtiI2jf6YpultF1+Hg5+IK863wKpiNmJbxmA+AOc171LVmNlqiSdDp2fptfIgaI5IMcLMJj8zvY2gghAGoRrchpSkteTLc48om87Duw1gR5lAZjUYzNON9wETte9bfUvQ6/ZkQE3rjEUY6TfyokKJf4X/0ZxKFz0YzkcHDXBaPefrIWxQGygeTsy0kZO7UKpYZo)
  aes:
    defaultKey: ENC(KdXXhvt6v7BDw7MgsR4J1OgahZgjl3kEil10+147oGA=)
    iv: ENC(Gtzf6s+BRoC1iQsRLMswSlBDSMom0kWtx5+SMJgaVDg=)
src/main/resources/config/application-prod.yml
@@ -62,4 +62,25 @@
  community: public
  retries: 1
  timeout: 5000
jasypt:
  encryptor:
    password: hELEEWWEEr9Lu6HgEvttjj8vYhy3ID+PqPbumuXhcHhe
    algorithm: PBEWithMD5AndDES
    iv-generator-classname: org.jasypt.iv.NoIvGenerator
custom:
  #登录验证码 on/off
  fontDynamicCode: on
  #允许跨域的白名单 http://192.168.10.132:8080,http://192.168.10.109:8080
  cors: http://localhost:8080,http://192.168.10.114:8080,,http://192.168.10.86:8080
  #重启密码
  restartPasswd: ENC(AKxTGQo6bAABeC62B8Dtxw==)
  rsa:
    #publicKeyOld: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCPpJ3j+SHQ69lqq+ShV7deA40Y+8rYra6rr4ReOJ+UE7ek8tsJJrcy1xMO1SophJdHXXwSNbZWhnJW9GlIq1Um6IplkwFc/AtyoeJDP3EJtUZgI5H6fSz0BPLFHn18C0Nxz1Br109U07DqQdMsarcBmKXYQw+2oZOz0KpA5b0FawIDAQAB
    #privateKeyOld: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI+kneP5IdDr2Wqr5KFXt14DjRj7ytitrquvhF44n5QTt6Ty2wkmtzLXEw7VKimEl0ddfBI1tlaGclb0aUirVSboimWTAVz8C3Kh4kM/cQm1RmAjkfp9LPQE8sUefXwLQ3HPUGvXT1TTsOpB0yxqtwGYpdhDD7ahk7PQqkDlvQVrAgMBAAECgYA8ASdX4W2n6a4kKnRSleLqqg8aHazqAPvTinmAJqU65VW02SJ42yxyV3gFnTSErXfIfxviO3/U+0ruWiFVEwV5oDEh0dOd+HHGm4YzFXIRglMeRBgLuVJ+owzoVDwZstiIBa69DIjaJtmpSf5FjwxAth+gtCv3e11IXHraKN720QJBAMPMB1WtmpRGYHxWVYjKSL+RGw+h3gMQLk3exZjhmYRlXuqfVZ2Zol+NazDc59K5f+geMdJ0/X2kKnKLVjWzYHMCQQC7z1cFYswtLemxGfj+dwlVC01VL4pKa7HGHl/FAQ2UNYZY2d5hE/nXYbTpfI0gMowX926/aFpia7NbAUJO7WEpAkAyUFa+LJthaOhYazMVsK2bFKW4kabkcJ8Fga6TR73UaNxIPGOa2SUBmuylpM6ptuNoeYHiDBAr3ijOQIIJ0KuDAkBy9fPahCNe9F+73J4hhVPdDtIDdto7u7hSAX215XMeabUW5iXNXqDsSg6nbWolb0t50CemWoYZALwE1Lx1+7AhAkEAoZtFt+2skjAxHEqNUye4vKBqB2Ng/wmfitCfT34lXWQsxs4BGk/8eQMzkam9bcB7FcinolxHF/1UjsUYpI+AgA==
    publicKey: ENC(QR8EpIC0jzG2E29Dhtq/vqrwt99WtUix/h2J8OvD90w0fosfUM1EFpdHJ2nsdP84BOeVNoPmudqXCYWVeCuTrVkqfb2z8mMLDl8cry78P8Tu4il3m9hGxqjdeNJbdYA6z6eRaInoJj5BHUyNpAJDaNacMZoOUJU6lMySwujyrD8PfSY97St0XPL5GIFP9rP1FCnlVWBeH4tqZKZ6MGncYJaITUZ/BIPkhpDYxi+i4CnMIBqytCJ6OJCzjLBI44UsQOzsdLgppAE2O0fmgyXA6bh0VRdIaRhqDIrjur2e4sOEvjadORN0Kg==)
    privateKey: ENC(fDshYRxHSlpJ2v+CmDGzH/PlFIKr9+hcPg0patE+nOFMKQaEVNLj9XxOlGEDFabSLFvy1imSRmOF08EE/z9cmlsp+hfbF6feR6YABRHgDxOGWusZ9QKYLhv6vDD6pebKb2W3FCuIHnLicMiJfzpM5KGylTMv7rvtM7tFR8ZhDzn3s8uYotz6ORcfCPdgOcUcNHXT0WS2KA0NigsRH5YMF5IOCP2jNTaOFDDXYacjfGOwjFIGE71BMJCnMRp6RnukbAY1ZN3J88GpYRzYCYD/S9DbGFVY9giH0T7FZs5cgPsCoDZ1dIeJhmjbOxoQpwKoDZzvlYbsstMH+6wApaWgx9TJfBoNjEJdqM1S3asukV4bUq4cZnmryCeSWSYkR2FDuH792rXL3Msh2Jc2hB2Cg9ZPB5hljN5GWV0fYiKNjJW2ovgBZZRWURorkrfBReKsxuLcHlbBcdHBF9DZDJyy40fg9GP6w40uG3hBKd/OlA9IYWNWEgqgeMkNmesG9RTc4X7EG2Ar4MEDa1p6o3unIve/zTCpLoFzKCRIjYcqlW1pZfSwZD4wu6JJf+5tUoXaEEf5YD4dcWCD4DzUcv4qhOpHXDBtM3E45VdacMWZNdE7fXcDzWpgYdUSQ88HsXRjmaW0O/x5irdN5KGa89yj5bDYQeMzR7Cervxml3MUZSrkHVKsa9yWverlLaRXzTue3+MXgDudm1stHju5p2x55GWG9ZfcErDoTNqhgPwcbJnW7/vXFpoTt6AF3t8vbD7f5G+FXnvYLDUWtdNS8KN6X+EOkh4GWootC+QMEKArDr8AyL+5D2TkBGIDMAag/LVwAKSwvBs2+e/xsSlw+AuAsWcfb9whJCZNVogpA1jE56SIdIBtw4G4Lw9LMlJ2MprkV6e2VAtBwpou3fd5pUsKpu51WBfISRy60vls7Fu0mQXrT7cCzThptrk9KgIhjMtiI2jf6YpultF1+Hg5+IK863wKpiNmJbxmA+AOc171LVmNlqiSdDp2fptfIgaI5IMcLMJj8zvY2gghAGoRrchpSkteTLc48om87Duw1gR5lAZjUYzNON9wETte9bfUvQ6/ZkQE3rjEUY6TfyokKJf4X/0ZxKFz0YzkcHDXBaPefrIWxQGygeTsy0kZO7UKpYZo)
  aes:
    defaultKey: ENC(KdXXhvt6v7BDw7MgsR4J1OgahZgjl3kEil10+147oGA=)
    iv: ENC(Gtzf6s+BRoC1iQsRLMswSlBDSMom0kWtx5+SMJgaVDg=)
  i18n: zh-CN
src/main/resources/mapper/UserInfMapper.xml
New file
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.whyc.mapper.UserInfMapper">
    <update id="createNumber">
        CREATE TABLE if not exists db_user.temp_numbers (unumber INT);
    </update>
    <update id="setUnumber">
        ${sql}
    </update>
    <select id="existTable" resultType="java.lang.String">
        select
            DISTINCT table_name
        from information_schema.tables
        where table_name = 'temp_numbers'
          and TABLE_SCHEMA = 'db_user'
    </select>
    <select id="selectSnId" resultType="java.lang.String">
        select usnid from db_user.user_inf where uname=#{uname} limit 1
    </select>
    <select id="judgeUname" resultType="java.lang.Integer">
        select count(*) from  db_user.user_inf where uid>100
    </select>
    <select id="getAllUser" resultType="UserInf">
        select uid,uname,udownload_role from db_user.user_inf where uid>100
    </select>
    <select id="getIn1000" resultType="java.lang.String">
        SELECT min(unumber)
        FROM db_user.temp_numbers t
        WHERE t.unumber NOT IN (SELECT uid FROM db_user.user_inf);
    </select>
    <select id="getMaxUid" resultType="java.lang.String">
        SELECT max(uid)
        FROM db_user.user_inf  where uid>1000
    </select>
</mapper>