天天看点

jeecg-boot的shiro认证过程2. jwtFilter

  1. shrio配置

说明:

  • 首先配置一系列拦截的路径
  • 配置jwtfilter 继承AuthenticatingFilter 作后面的接口登录验证
  • 自定义realm
  • 实例化常规bean
  1. package com.hnlrkj.talentgift.config.shiro;

    import com.hnlrkj.talentgift.config.shiro.filters.CustomShiroFilterFactoryBean;

    import com.hnlrkj.talentgift.config.shiro.filters.JwtFilter;

    import com.hnlrkj.talentgift.common.constant.CommonConstant;

    import com.hnlrkj.talentgift.common.util.oConvertUtils;

    import lombok.extern.slf4j.Slf4j;

    import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;

    import org.apache.shiro.mgt.DefaultSubjectDAO;

    import org.apache.shiro.mgt.SecurityManager;

    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.crazycake.shiro.IRedisManager;

    import org.crazycake.shiro.RedisCacheManager;

    import org.crazycake.shiro.RedisClusterManager;

    import org.crazycake.shiro.RedisManager;

    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.beans.factory.annotation.Value;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Configuration;

    import org.springframework.context.annotation.DependsOn;

    import org.springframework.core.env.Environment;

    import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

    import org.springframework.util.StringUtils;

    import redis.clients.jedis.HostAndPort;

    import redis.clients.jedis.JedisCluster;

    import javax.annotation.Resource;

    import javax.servlet.Filter;

    import java.util.*;

    @Slf4j

    @Configuration

    public class ShiroConfig {

        @Value("${talentgift.shiro.excludeUrls}")

        private String excludeUrls;

        @Resource

        LettuceConnectionFactory lettuceConnectionFactory;

        @Autowired

        private Environment env;

        @Bean("shiroFilter")

        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {

            CustomShiroFilterFactoryBean shiroFilterFactoryBean = new CustomShiroFilterFactoryBean();

            shiroFilterFactoryBean.setSecurityManager(securityManager);

            // 拦截器

            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();

            if(oConvertUtils.isNotEmpty(excludeUrls)){

                String[] permissionUrl = excludeUrls.split(",");

                for(String url : permissionUrl){

                    filterChainDefinitionMap.put(url,"anon");

                }

            }

            // 配置不会被拦截的链接 顺序判断

            filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录

            filterChainDefinitionMap.put("/sys/randomImage*.js", "anon");

            filterChainDefinitionMap.put("*.css", "anon");

            filterChainDefinitionMap.put("*.html", "anon");

            filterChainDefinitionMap.put("*.svg", "anon");

            filterChainDefinitionMap.put("*.pdf", "anon");

            filterChainDefinitionMap.put("*.jpg", "anon");

            filterChainDefinitionMap.put("*.png", "anon");

            filterChainDefinitionMap.put("*.ico", "anon");

            filterChainDefinitionMap.put("*.ttf", "anon");

            filterChainDefinitionMap.put("*.woff", "anon");

            filterChainDefinitionMap.put("*.woff2", "anon");

            filterChainDefinitionMap.put("/druid**", "anon");

            filterChainDefinitionMap.put("/webjars*.js.map", "anon");

            filterChainDefinitionMap.put("*.css.map", "anon");

            //大屏设计器排除

            filterChainDefinitionMap.put("/bigscreen

            DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();

            DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();

            defaultSessionStorageEvaluator.setSessionStorageEnabled(false);

            subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);

            securityManager.setSubjectDAO(subjectDAO);

            //自定义缓存实现,使用redis

            securityManager.setCacheManager(redisCacheManager());

            return securityManager;

        }

        @Bean

        @DependsOn("lifecycleBeanPostProcessor")

        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {

            DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();

            defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);

            defaultAdvisorAutoProxyCreator.setUsePrefix(true);

            defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor");

            return defaultAdvisorAutoProxyCreator;

        }

        @Bean

        public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {

            return new LifecycleBeanPostProcessor();

        }

        @Bean

        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {

            AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();

            advisor.setSecurityManager(securityManager);

            return advisor;

        }

        public RedisCacheManager redisCacheManager() {

            log.info("===============(1)创建缓存管理器RedisCacheManager");

            RedisCacheManager redisCacheManager = new RedisCacheManager();

            redisCacheManager.setRedisManager(redisManager());

            //redis中针对不同用户缓存(此处的id需要对应user实体中的id字段,用于唯一标识)

            redisCacheManager.setPrincipalIdFieldName("id");

            //用户权限信息缓存时间

            redisCacheManager.setExpire(200000);

            return redisCacheManager;

        }

        @Bean

        public IRedisManager redisManager() {

            log.info("===============(2)创建RedisManager,连接Redis..");

            IRedisManager manager;

            // redis 单机支持,在集群为空,或者集群无机器时候使用 add by [email protected]

            if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {

                RedisManager redisManager = new RedisManager();

                redisManager.setHost(lettuceConnectionFactory.getHostName());

                redisManager.setPort(lettuceConnectionFactory.getPort());

                redisManager.setDatabase(lettuceConnectionFactory.getDatabase());

                redisManager.setTimeout(0);

                if (!StringUtils.isEmpty(lettuceConnectionFactory.getPassword())) {

                    redisManager.setPassword(lettuceConnectionFactory.getPassword());

                }

                manager = redisManager;

            }else{

                // redis集群支持,优先使用集群配置

                RedisClusterManager redisManager = new RedisClusterManager();

                Set<HostAndPort> portSet = new HashSet<>();

                lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost() , node.getPort())));

                JedisCluster jedisCluster = new JedisCluster(portSet);

                redisManager.setJedisCluster(jedisCluster);

                manager = redisManager;

            }

            return manager;

        }

    }

2. jwtFilter

说明

  • 该过滤器主要是通过对前端传的head中的token进行用户身份的验证
  • getSubject(request, response).login(jwtToken); 交给realm认证
package com.hnlrkj.talentgift.config.shiro.filters;



import com.hnlrkj.talentgift.common.constant.CommonConstant;

import com.hnlrkj.talentgift.config.mybatis.TenantContext;

import com.hnlrkj.talentgift.config.shiro.JwtToken;

import lombok.extern.slf4j.Slf4j;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;

import org.springframework.http.HttpStatus;

import org.springframework.web.bind.annotation.RequestMethod;



import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;



/**

 * @Description: 鉴权登录拦截器

 * @Author:

 * @Date:

 **/

@Slf4j

public class JwtFilter extends BasicHttpAuthenticationFilter {



    private boolean allowOrigin = true;



    public JwtFilter(){}

    public JwtFilter(boolean allowOrigin){

        this.allowOrigin = allowOrigin;

    }



    /**

     * 执行登录认证

     *

     * @param request

     * @param response

     * @param mappedValue

     * @return

     */

    @Override

    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {

        try {

            executeLogin(request, response);

            return true;

        } catch (Exception e) {

            throw new AuthenticationException("Token失效,请重新登录", e);

        }

    }



    /**

     *

     */

    @Override

    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        String token = httpServletRequest.getHeader(CommonConstant.X_ACCESS_TOKEN);

        // update-begin--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数

        if(token == null){

            token = httpServletRequest.getParameter("token");

        }

        // update-end--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数



        JwtToken jwtToken = new JwtToken(token);

        // 提交给realm进行登入,如果错误他会抛出异常并被捕获

        getSubject(request, response).login(jwtToken);

        // 如果没有抛出异常则代表登入成功,返回true

        return true;

    }



    /**

     * 对跨域提供支持

     */

    @Override

    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        if(allowOrigin){

            httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));

            httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");

            httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));

            //update-begin-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题

            // 是否允许发送Cookie,默认Cookie不包括在CORS请求之中。设为true时,表示服务器允许Cookie包含在请求中。

            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");

            //update-end-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题

        }

        // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态

        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {

            httpServletResponse.setStatus(HttpStatus.OK.value());

            return false;

        }

        //update-begin-author:taoyan date:20200708 for:多租户用到

        String tenant_id = httpServletRequest.getHeader(CommonConstant.TENANT_ID);

        TenantContext.setTenant(tenant_id);

        //update-end-author:taoyan date:20200708 for:多租户用到

        return super.preHandle(request, response);

    }

}
           
  1. 最后的登录接口

说明:

  • 常规通过查询数据库判断用户有效性
  • 通过jwt工具类,签发token,返回到前端
  • package com.hnlrkj.talentgift.modules.system.controller;

    import cn.hutool.core.util.RandomUtil;

    import com.alibaba.fastjson.JSONObject;

    import com.aliyuncs.exceptions.ClientException;

    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

    import com.hnlrkj.talentgift.common.util.*;

    import com.hnlrkj.talentgift.common.util.RedisUtil;

    import com.hnlrkj.talentgift.common.api.vo.Result;

    import com.hnlrkj.talentgift.common.constant.CacheConstant;

    import com.hnlrkj.talentgift.common.constant.CommonConstant;

    import com.hnlrkj.talentgift.common.system.api.ISysBaseAPI;

    import com.hnlrkj.talentgift.common.system.util.JwtUtil;

    import com.hnlrkj.talentgift.common.system.vo.LoginUser;

    import com.hnlrkj.talentgift.common.util.encryption.EncryptedString;

    import com.hnlrkj.talentgift.modules.base.service.BaseCommonService;

    import com.hnlrkj.talentgift.modules.system.entity.SysDepart;

    import com.hnlrkj.talentgift.modules.system.entity.SysPermission;

    import com.hnlrkj.talentgift.modules.system.entity.SysRole;

    import com.hnlrkj.talentgift.modules.system.entity.SysUser;

    import com.hnlrkj.talentgift.modules.system.model.SysLoginModel;

    import com.hnlrkj.talentgift.modules.system.service.*;

    import com.hnlrkj.talentgift.modules.system.util.PermissionDataUtil;

    import com.hnlrkj.talentgift.modules.system.util.RandImageUtil;

    import com.hnlrkj.util.core.CheckUtil;

    import io.swagger.annotations.Api;

    import io.swagger.annotations.ApiOperation;

    import lombok.extern.slf4j.Slf4j;

    import org.apache.shiro.SecurityUtils;

    import org.springframework.beans.BeanUtils;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.web.bind.annotation.*;

    import javax.annotation.Resource;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import java.util.*;

    @RestController

    @RequestMapping("/sys")

    @Api(tags = "用户登录")

    @Slf4j

    public class LoginController {

        @Autowired

        private ISysUserService sysUserService;

        @Autowired

        private ISysBaseAPI sysBaseAPI;

        @Autowired

        private ISysLogService logService;

        @Autowired

        private RedisUtil redisUtil;

        @Autowired

        private ISysDepartService sysDepartService;

        @Autowired

        private ISysDictService sysDictService;

        @Resource

        private BaseCommonService baseCommonService;

        @Autowired

        private ISysRoleService sysRoleService;

        @Autowired

        private ISysPermissionService sysPermissionService;

        private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";

        @ApiOperation("登录接口")

        @RequestMapping(value = "/login", method = RequestMethod.POST)

        public Result<JSONObject> login(SysLoginModel sysLoginModel) {

            Result<JSONObject> result = new Result<JSONObject>();

            String username = sysLoginModel.getUsername();

            String password = sysLoginModel.getPassword();

            //update-begin--Author:scott  Date:20190805 for:暂时注释掉密码加密逻辑,有点问题

            //前端密码加密,后端进行密码解密

            //password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密

            //update-begin--Author:scott  Date:20190805 for:暂时注释掉密码加密逻辑,有点问题

            //update-begin-author:taoyan date:20190828 for:校验验证码

            String captcha = sysLoginModel.getCaptcha();

            if (captcha == null) {

                result.error500("验证码无效");

                return result;

            }

            String lowerCaseCaptcha = captcha.toLowerCase();

            String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + sysLoginModel.getCheckKey(), "utf-8");

            Object checkCode = redisUtil.get(realKey);

            //当进入登录页时,有一定几率出现验证码错误 #1714

            if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {

                result.error500("验证码错误");

                return result;

            }

            //update-end-author:taoyan date:20190828 for:校验验证码

            //1. 校验用户是否有效

            //update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false

            LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();

            queryWrapper.eq(SysUser::getUsername, username);

            SysUser sysUser = sysUserService.getOne(queryWrapper);

            //update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false

            result = sysUserService.checkUserIsEffective(sysUser);

            if (!result.isSuccess()) {

                return result;

            }

            //2. 校验用户名或密码是否正确

            String userpassword = PasswordUtil.encrypt(null, password, sysUser.getSalt());

            String syspassword = sysUser.getPassword();

            if (!syspassword.equals(userpassword)) {

                result.error500("用户名或密码错误");

                return result;

            }

            //用户登录信息

            userInfo(sysUser, result);

            //update-begin--Author:liusq  Date:20210126  for:登录成功,删除redis中的验证码

            redisUtil.del(realKey);

            //update-begin--Author:liusq  Date:20210126  for:登录成功,删除redis中的验证码

            LoginUser loginUser = new LoginUser();

            BeanUtils.copyProperties(sysUser, loginUser);

            //返回用户角色

            List<SysRole> role = sysRoleService.getRoleByUserId(sysUser.getId());

            if(null!=role&&role.size()>0){

                StringBuffer buffer = new StringBuffer();

                role.forEach(s->{

                    if(CheckUtil.notEmpty(s)&&null!=s){

                        if(null!=buffer&&!"".equals(buffer.toString())){

                            buffer.append(",");

                        }

                        buffer.append(s.getRoleCode());

                    }

                });

                loginUser.setRoles(buffer.toString());

                result.getResult().put("roles",loginUser.getRoles());

                boolean home = false;

                //返回用户角色

                List<SysRole> sRole = sysRoleService.getRoleByUserId(loginUser.getId());

                SysPermission indexMenu = new SysPermission();

                if(null!=sRole){

                    indexMenu = sysPermissionService.queryRoleCode("首页",sRole.get(0).getRoleCode());

                    if(null!=indexMenu){

                        home = true;

                    }

                }

                //判断是否有首页

                if(home){

                    result.getResult().put("url",indexMenu.getUrl());

                }else{

                    result.getResult().put("url",null);

                }

            }

            baseCommonService.addLog("用户名: " + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null, loginUser);

            return result;

        }

        @RequestMapping(value = "/logout")

        public Result<Object> logout(HttpServletRequest request, HttpServletResponse response) {

            //用户退出逻辑

            String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);

            if (oConvertUtils.isEmpty(token)) {

                return Result.error("退出登录失败!");

            }

            String username = JwtUtil.getUsername(token);

            LoginUser sysUser = sysBaseAPI.getUserByName(username);

            if (sysUser != null) {

                //update-begin--Author:wangshuai  Date:20200714  for:登出日志没有记录人员

                baseCommonService.addLog("用户名: " + sysUser.getRealname() + ",退出成功!", CommonConstant.LOG_TYPE_1, null, sysUser);

                //update-end--Author:wangshuai  Date:20200714  for:登出日志没有记录人员

                log.info(" 用户名:  " + sysUser.getRealname() + ",退出成功! ");

                //清空用户登录Token缓存

                redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);

                //清空用户登录Shiro权限缓存

                redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());

                //清空用户的缓存信息(包括部门信息),例如sys:cache:user::<username>

                redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));

                //调用shiro的logout

                SecurityUtils.getSubject().logout();

                return Result.ok("退出登录成功!");

            } else {

                return Result.error("Token无效!");

            }

        }

        @GetMapping("loginfo")

        public Result<JSONObject> loginfo() {

            Result<JSONObject> result = new Result<JSONObject>();

            JSONObject obj = new JSONObject();

            //update-begin--Author:zhangweijian  Date:20190428 for:传入开始时间,结束时间参数

            // 获取一天的开始和结束时间

            Calendar calendar = new GregorianCalendar();

            calendar.set(Calendar.HOUR_OF_DAY, 0);

            calendar.set(Calendar.MINUTE, 0);

            calendar.set(Calendar.SECOND, 0);

            calendar.set(Calendar.MILLISECOND, 0);

            Date dayStart = calendar.getTime();

            calendar.add(Calendar.DATE, 1);

            Date dayEnd = calendar.getTime();

            // 获取系统访问记录

            Long totalVisitCount = logService.findTotalVisitCount();

            obj.put("totalVisitCount", totalVisitCount);

            Long todayVisitCount = logService.findTodayVisitCount(dayStart, dayEnd);

            obj.put("todayVisitCount", todayVisitCount);

            Long todayIp = logService.findTodayIp(dayStart, dayEnd);

            //update-end--Author:zhangweijian  Date:20190428 for:传入开始时间,结束时间参数

            obj.put("todayIp", todayIp);

            result.setResult(obj);

            result.success("登录成功");

            return result;

        }

        @GetMapping("visitInfo")

        public Result<List<Map<String, Object>>> visitInfo() {

            Result<List<Map<String, Object>>> result = new Result<List<Map<String, Object>>>();

            Calendar calendar = new GregorianCalendar();

            calendar.set(Calendar.HOUR_OF_DAY, 0);

            calendar.set(Calendar.MINUTE, 0);

            calendar.set(Calendar.SECOND, 0);

            calendar.set(Calendar.MILLISECOND, 0);

            calendar.add(Calendar.DAY_OF_MONTH, 1);

            Date dayEnd = calendar.getTime();

            calendar.add(Calendar.DAY_OF_MONTH, -7);

            Date dayStart = calendar.getTime();

            List<Map<String, Object>> list = logService.findVisitCount(dayStart, dayEnd);

            result.setResult(oConvertUtils.toLowerCasePageList(list));

            return result;

        }

        @RequestMapping(value = "/selectDepart", method = RequestMethod.PUT)

        public Result<JSONObject> selectDepart(SysUser user) {

            Result<JSONObject> result = new Result<JSONObject>();

            String username = user.getUsername();

            if (oConvertUtils.isEmpty(username)) {

                LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

                username = sysUser.getUsername();

            }

            String orgCode = user.getOrgCode();

            this.sysUserService.updateUserDepart(username, orgCode);

            SysUser sysUser = sysUserService.getUserByName(username);

            JSONObject obj = new JSONObject();

            obj.put("userInfo", sysUser);

            result.setResult(obj);

            return result;

        }

        @PostMapping(value = "/sms")

        public Result<String> sms(JSONObject jsonObject) {

            Result<String> result = new Result<String>();

            String mobile = jsonObject.get("mobile").toString();

            //手机号模式 登录模式: "2"  注册模式: "1"

            String smsmode = jsonObject.get("smsmode").toString();

            log.info(mobile);

            if (oConvertUtils.isEmpty(mobile)) {

                result.setMessage("手机号不允许为空!");

                result.setSuccess(false);

                return result;

            }

            Object object = redisUtil.get(mobile);

            if (object != null) {

                result.setMessage("验证码10分钟内,仍然有效!");

                result.setSuccess(false);

                return result;

            }

            //随机数

            String captcha = RandomUtil.randomNumbers(6);

            JSONObject obj = new JSONObject();

            obj.put("code", captcha);

            try {

                boolean b = false;

                //注册模板

                if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) {

                    SysUser sysUser = sysUserService.getUserByPhone(mobile);

                    if (sysUser != null) {

                        result.error500(" 手机号已经注册,请直接登录!");

                        baseCommonService.addLog("手机号已经注册,请直接登录!", CommonConstant.LOG_TYPE_1, null);

                        return result;

                    }

                    b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.REGISTER_TEMPLATE_CODE);

                } else {

                    //登录模式,校验用户有效性

                    SysUser sysUser = sysUserService.getUserByPhone(mobile);

                    result = sysUserService.checkUserIsEffective(sysUser);

                    if (!result.isSuccess()) {

                        String message = result.getMessage();

                        if ("该用户不存在,请注册".equals(message)) {

                            result.error500("该用户不存在或未绑定手机号");

                        }

                        return result;

                    }

                    if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {

                        //登录模板

                        b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);

                    } else if (CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {

                        //忘记密码模板

                        b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);

                    }

                }

                if (b == false) {

                    result.setMessage("短信验证码发送失败,请稍后重试");

                    result.setSuccess(false);

                    return result;

                }

                //验证码10分钟内有效

                redisUtil.set(mobile, captcha, 600);

                //update-begin--Author:scott  Date:20190812 for:issues#391

                //result.setResult(captcha);

                //update-end--Author:scott  Date:20190812 for:issues#391

                result.setSuccess(true);

            } catch (ClientException e) {

                e.printStackTrace();

                result.error500(" 短信接口未配置,请联系管理员!");

                return result;

            }

            return result;

        }

        @ApiOperation("手机号登录接口")

        @PostMapping("/phoneLogin")

        public Result<JSONObject> phoneLogin(JSONObject jsonObject) {

            Result<JSONObject> result = new Result<JSONObject>();

            String phone = jsonObject.getString("mobile");

            //校验用户有效性

            SysUser sysUser = sysUserService.getUserByPhone(phone);

            result = sysUserService.checkUserIsEffective(sysUser);

            if (!result.isSuccess()) {

                return result;

            }

            String smscode = jsonObject.getString("captcha");

            Object code = redisUtil.get(phone);

            if (!smscode.equals(code)) {

                result.setMessage("手机验证码错误");

                return result;

            }

            //用户信息

            userInfo(sysUser, result);

            //添加日志

            baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功!", CommonConstant.LOG_TYPE_1, null);

            return result;

        }

        private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {

            String syspassword = sysUser.getPassword();

            String username = sysUser.getUsername();

            // 生成token

            String token = JwtUtil.sign(username, syspassword);

            // 设置token缓存有效时间

            redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);

            redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);

            // 获取用户部门信息

            JSONObject obj = new JSONObject();

            List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());

            obj.put("departs", departs);

            if (departs == null || departs.size() == 0) {

                obj.put("multi_depart", 0);

            } else if (departs.size() == 1) {

                sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());

                obj.put("multi_depart", 1);

            } else {

                //查询当前是否有登录部门

                // update-begin--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去

                SysUser sysUserById = sysUserService.getById(sysUser.getId());

                if (oConvertUtils.isEmpty(sysUserById.getOrgCode())) {

                    sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());

                }

                // update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去

                obj.put("multi_depart", 2);

            }

            obj.put("token", token);

            obj.put("userInfo", sysUser);

            obj.put("sysAllDictItems", sysDictService.queryAllDictItems());

            result.setResult(obj);

            result.success("登录成功");

            return result;

        }

        @GetMapping(value = "/getEncryptedString")

        public Result<Map<String, String>> getEncryptedString() {

            Result<Map<String, String>> result = new Result<Map<String, String>>();

            Map<String, String> map = new HashMap<String, String>();

            map.put("key", EncryptedString.key);

            map.put("iv", EncryptedString.iv);

            result.setResult(map);

            return result;

        }

        @ApiOperation("获取验证码")

        @GetMapping(value = "/randomImage/{key}")

        public Result<String> randomImage(HttpServletResponse response, @PathVariable String key) {

            Result<String> res = new Result<String>();

            try {

                String code = RandomUtil.randomString(BASE_CHECK_CODES, 4);

                String lowerCaseCode = code.toLowerCase();

                String realKey = MD5Util.MD5Encode(lowerCaseCode + key, "utf-8");

                redisUtil.set(realKey, lowerCaseCode, 60);

                String base64 = RandImageUtil.generate(code);

                res.setSuccess(true);

                res.setResult(base64);

            } catch (Exception e) {

                res.error500("获取验证码出错" + e.getMessage());

                e.printStackTrace();

            }

            return res;

        }

        @RequestMapping(value = "/mLogin", method = RequestMethod.POST)

        public Result<JSONObject> mLogin(SysLoginModel sysLoginModel) throws Exception {

            Result<JSONObject> result = new Result<JSONObject>();

            String username = sysLoginModel.getUsername();

            String password = sysLoginModel.getPassword();

            //1. 校验用户是否有效

            SysUser sysUser = sysUserService.getUserByName(username);

            result = sysUserService.checkUserIsEffective(sysUser);

            if (!result.isSuccess()) {

                return result;

            }

            //2. 校验用户名或密码是否正确

            String userpassword = PasswordUtil.encrypt(null, password, sysUser.getSalt());

            String syspassword = sysUser.getPassword();

            if (!syspassword.equals(userpassword)) {

                result.error500("用户名或密码错误");

                return result;

            }

            String orgCode = sysUser.getOrgCode();

            if (oConvertUtils.isEmpty(orgCode)) {

                //如果当前用户无选择部门 查看部门关联信息

                List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());

                if (departs == null || departs.size() == 0) {

                    result.error500("用户暂未归属部门,不可登录!");

                    return result;

                }

                orgCode = departs.get(0).getOrgCode();

                sysUser.setOrgCode(orgCode);

                this.sysUserService.updateUserDepart(username, orgCode);

            }

            JSONObject obj = new JSONObject();

            //用户登录信息

            obj.put("userInfo", sysUser);

            // 生成token

            String token = JwtUtil.sign(username, syspassword);

            // 设置超时时间

            redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);

            redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);

            //token 信息

            obj.put("token", token);

            result.setResult(obj);

            result.setSuccess(true);

            result.setCode(200);

            baseCommonService.addLog("用户名: " + username + ",登录成功[移动端]!", CommonConstant.LOG_TYPE_1, null);

            return result;

        }

        @RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)

        public Result<?> checkCaptcha(SysLoginModel sysLoginModel) {

            String captcha = sysLoginModel.getCaptcha();

            String checkKey = sysLoginModel.getCheckKey();

            if (captcha == null) {

                return Result.error("验证码无效");

            }

            String lowerCaseCaptcha = captcha.toLowerCase();

            String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + checkKey, "utf-8");

            Object checkCode = redisUtil.get(realKey);

            if (checkCode == null || !checkCode.equals(lowerCaseCaptcha)) {

                return Result.error("验证码错误");

            }

            return Result.ok();

        }

  • /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
        String syspassword = sysUser.getPassword();
        String username = sysUser.getUsername();
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
    
        // 获取用户部门信息
        JSONObject obj = new JSONObject();
        List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
        obj.put("departs", departs);
        if (departs == null || departs.size() == 0) {
            obj.put("multi_depart", 0);
        } else if (departs.size() == 1) {
            sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            obj.put("multi_depart", 1);
        } else {
            //查询当前是否有登录部门
            // update-begin--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
            SysUser sysUserById = sysUserService.getById(sysUser.getId());
            if (oConvertUtils.isEmpty(sysUserById.getOrgCode())) {
                sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            }
            // update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
            obj.put("multi_depart", 2);
        }
        obj.put("token", token);
        obj.put("userInfo", sysUser);
        obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }      
    }