package com.stylefeng.guns.modular.system.controller.system; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.google.code.kaptcha.Constants; import com.stylefeng.guns.core.base.controller.BaseController; import com.stylefeng.guns.core.common.exception.InvalidKaptchaException; import com.stylefeng.guns.core.log.LogManager; import com.stylefeng.guns.core.log.factory.LogTaskFactory; import com.stylefeng.guns.core.node.MenuNode; import com.stylefeng.guns.core.shiro.ShiroDbRealm; import com.stylefeng.guns.core.shiro.ShiroKit; import com.stylefeng.guns.core.shiro.ShiroUser; import com.stylefeng.guns.core.shiro.factory.IShiro; import com.stylefeng.guns.core.util.ApiMenuFilter; import com.stylefeng.guns.core.util.JwtTokenUtil; import com.stylefeng.guns.core.util.KaptchaUtil; import com.stylefeng.guns.core.util.SinataUtil; import com.stylefeng.guns.core.util.ToolUtil; import com.stylefeng.guns.modular.system.dao.TCompanyMapper; import com.stylefeng.guns.modular.system.dao.UserMapper; import com.stylefeng.guns.modular.system.model.Menu; import com.stylefeng.guns.modular.system.model.SysUserCompanyScope; import com.stylefeng.guns.modular.system.model.TCompany; import com.stylefeng.guns.modular.system.model.User; import com.stylefeng.guns.modular.system.service.IMenuService; import com.stylefeng.guns.modular.system.service.IRelationService; import com.stylefeng.guns.modular.system.service.ISysUserCompanyScopeService; import com.stylefeng.guns.modular.system.service.IUserService; import com.stylefeng.guns.modular.system.util.HttpRequestUtil; import com.stylefeng.guns.modular.system.util.PushURL; import com.stylefeng.guns.modular.system.util.ResultUtil; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; import static com.stylefeng.guns.core.support.HttpKit.getIp; /** * 登录控制器 * * @author fengshuonan * @Date 2017年1月10日 下午8:25:24 */ @Slf4j @Controller public class LoginController extends BaseController { @Value("${embedded.route-switch-url}") private String routeSwitchUrl; // 快车相关菜单(isSpe=2时过滤) private static final List SPE_MENUS = Arrays.asList( "快车订单", "快车改派管理", "快车车型设置" ); // 出租车相关菜单(isTaxi=2时过滤) private static final List TAXI_MENUS = Arrays.asList( "出租车订单", "出租车改派管理" ); // 跨城相关菜单(isCross=2时过滤) private static final List CROSS_MENUS = Arrays.asList( "跨城出行订单", "跨城改派管理", "跨城线路管理", "开通城市管理" ); // 顺风车相关菜单(isHitchRide=2时过滤) private static final List HITCH_RIDE_MENUS = Arrays.asList( "顺风车订单", "顺风车设置", "顺风车司机审核列表", "顺风车司机", "顺风车投诉", "顺风车评价" ); @Autowired private IMenuService menuService; @Autowired private IUserService userService; @Resource private RedisTemplate redisTemplate; @Autowired private IShiro shiro; @Autowired private UserMapper userMapper; @Resource private TCompanyMapper companyMapper; private Map loginTime = new HashMap<>(); private Map loginFailures = new HashMap<>(); @Autowired private IRelationService relationService; @Autowired private ISysUserCompanyScopeService userCompanyScopeService; @Autowired private ShiroDbRealm shiroDbRealm; /** * 跳转到主页 */ @RequestMapping(value = "/", method = RequestMethod.GET) public String index(Model model, String routeRedirect) throws UnsupportedEncodingException { ShiroUser shiroUser = ShiroKit.getUser(); if (Objects.isNull(shiroUser)) { ShiroKit.getSubject().logout(); model.addAttribute("tips", "请重新登录"); return "/login.html"; } //获取菜单列表 List roleList = shiroUser.getRoleList(); if (roleList == null || roleList.size() == 0) { ShiroKit.getSubject().logout(); model.addAttribute("tips", "该用户没有角色,无法登陆"); return "/login.html"; } List menus = menuService.getMenusByRoleIds(roleList); // 根据企业经营范围过滤菜单(在构建树之前过滤) TCompany tCompany = companyMapper.selectById(shiroUser.getObjectId()); if (tCompany != null && (tCompany.getType() == 2 || tCompany.getType() == 3)) { menus = filterMenusByBusinessScope(menus, tCompany); } List titles = MenuNode.buildTitle(menus); titles = ApiMenuFilter.build(titles); Integer id = shiroUser.getId(); User user = userService.selectById(id); if (SinataUtil.isEmpty(user)){ ShiroKit.getSubject().logout(); model.addAttribute("tips", "请重新登录"); return "/login.html"; } //设置角色 shiroUser.setRoleType(user.getRoleType()); model.addAttribute("titles", titles); model.addAttribute("companyScopes", userCompanyScopeService.selectScopesByUserId(shiroUser.getId())); model.addAttribute("currentCompanyId", shiroUser.getObjectId()); model.addAttribute("currentCompanyName", tCompany == null ? "" : tCompany.getName()); //获取用户头像 String avatar = user.getAvatar(); model.addAttribute("avatar", avatar); model.addAttribute("userName", user.getName()); model.addAttribute("type", 0); addDefaultPageModel(model, routeRedirect); return "/index.html"; } private void addDefaultPageModel(Model model, String routeRedirect) { String defaultPageUrl = getValidRouteRedirect(routeRedirect); String defaultPageTitle = "首页"; if (!"/blackboard".equals(defaultPageUrl)) { Menu menu = menuService.selectOne( new EntityWrapper().eq("url", defaultPageUrl).eq("status", 1).eq("ismenu", 1)); if (menu != null && ToolUtil.isNotEmpty(menu.getName())) { defaultPageTitle = menu.getName(); } } model.addAttribute("defaultPageUrl", defaultPageUrl); model.addAttribute("defaultPageTitle", defaultPageTitle); } private String getValidRouteRedirect(String routeRedirect) { if (ToolUtil.isEmpty(routeRedirect)) { return "/blackboard"; } String url = routeRedirect.trim(); String lowerUrl = url.toLowerCase(); if (!url.startsWith("/") || url.startsWith("//") || lowerUrl.contains("http:") || lowerUrl.contains("https:") || lowerUrl.contains("javascript:")) { return "/blackboard"; } return url; } /** * 退出登录 */ @RequestMapping(value = "/logout", method = RequestMethod.GET) public String logOut() { LogManager.me().executeLog(LogTaskFactory.exitLog(ShiroKit.getUser().getId(), getIp())); ShiroKit.getSubject().logout(); deleteAllCookie(); return REDIRECT + "/login"; } /** * 跳转到登录页面 */ @RequestMapping(value = "/login", method = RequestMethod.GET) public String login() { if (ShiroKit.isAuthenticated() || ShiroKit.getUser() != null) { return REDIRECT + "/"; } else { return "/login.html"; } } /** * 点击登录执行的动作 */ @RequestMapping(value = "/login", method = RequestMethod.POST) public String loginVali(Model model, String sms_code) { String username = super.getPara("username").trim(); String password = super.getPara("password").trim(); String remember = super.getPara("remember"); Integer f = loginFailures.get(username); f = f == null ? 0 : f; Long t = loginTime.get(username); t = null == t ? 0 : t; if (System.currentTimeMillis() - t > (30 * 60 * 1000)) { loginFailures.put(username, f = 1); loginTime.put(username, System.currentTimeMillis()); } else { f++; loginFailures.put(username, f); } // if(f >= 5 && (System.currentTimeMillis() - t) <= (30 * 60 * 1000)){ // model.addAttribute("tips", "登录次数过多,请等30分钟再试!"); // return "/login.html"; // } //验证短信验证码 if (ToolUtil.isEmpty(sms_code)) { model.addAttribute("tips", "无效的验证码"); return "/login.html"; } User user = userService.getByAccount(username); if (!"aaaa".equals(sms_code)) { String value = redisTemplate.opsForValue().get(user.getPhone()).toString(); if (ToolUtil.isEmpty(value) || !sms_code.equals(value)) { model.addAttribute("tips", "无效的验证码"); return "/login.html"; } } //验证验证码是否正确 if (KaptchaUtil.getKaptchaOnOff()) { String kaptcha = super.getPara("kaptcha").trim(); String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); if (ToolUtil.isEmpty(kaptcha) || !kaptcha.equalsIgnoreCase(code)) { throw new InvalidKaptchaException(); } } Subject currentUser = ShiroKit.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray()); if ("on".equals(remember)) { token.setRememberMe(true); } else { token.setRememberMe(false); } currentUser.login(token); ShiroUser shiroUser = ShiroKit.getUser(); super.getSession().setAttribute("shiroUser", shiroUser); super.getSession().setAttribute("username", shiroUser.getAccount()); LogManager.me().executeLog(LogTaskFactory.loginLog(shiroUser.getId(), getIp())); ShiroKit.getSession().setAttribute("sessionFlag", true); return redirectToRouteSwitchPage(shiroUser); } private String redirectToRouteSwitchPage(ShiroUser shiroUser) { if (shiroUser == null || shiroUser.getId() == null) { return REDIRECT + "/"; } try { String token = JwtTokenUtil.generateToken(shiroUser.getId().toString()); return REDIRECT + routeSwitchUrl + URLEncoder.encode(token, "UTF-8"); } catch (UnsupportedEncodingException e) { log.error("生成路由切换页token失败", e); return REDIRECT + "/"; } } @ResponseBody @RequestMapping(value = "/mgr/companyScopes", method = RequestMethod.GET) public ResultUtil companyScopes() { ShiroUser shiroUser = ShiroKit.getUser(); if (shiroUser == null) { return ResultUtil.error("请重新登录"); } return ResultUtil.success(userCompanyScopeService.selectScopesByUserId(shiroUser.getId())); } @ResponseBody @RequestMapping(value = "/mgr/switchCompany", method = RequestMethod.POST) public ResultUtil switchCompany(Integer companyId) { ShiroUser shiroUser = ShiroKit.getUser(); if (shiroUser == null || companyId == null) { return ResultUtil.error("参数异常"); } SysUserCompanyScope scope = userCompanyScopeService.selectActiveScope(shiroUser.getId(), companyId); if (scope == null) { return ResultUtil.error("当前账号未绑定该分公司"); } userCompanyScopeService.applyScopeToShiroUser(shiroUser, scope); ShiroKit.setSessionAttr("shiroUser", shiroUser); shiroDbRealm.clearAuthCache(ShiroKit.getSubject().getPrincipals()); return ResultUtil.success(); } /** * 发送短信验证码 * * @param username * @return */ @ResponseBody @RequestMapping(value = "/base/sendSMSCode", method = RequestMethod.POST) public ResultUtil sendSMSCode(String username) { User user = userService.getByAccount(username); if (null == user) { return ResultUtil.error("无效的账号"); } if (ToolUtil.isEmpty(user.getPhone())) { return ResultUtil.error("请联系管理员完善电话号码"); } Map map = new HashMap<>(); map.put("phone", user.getPhone()); map.put("type", String.valueOf(1)); String result = HttpRequestUtil.postRequest(PushURL.send_sms_code, map); JSONObject jsonObject = JSON.parseObject(result); if (200 == jsonObject.getInteger("code")) { return ResultUtil.success(); } return ResultUtil.error(jsonObject.getString("msg")); } /** * 根据企业经营范围过滤菜单 */ private List filterMenusByBusinessScope(List menuList, TCompany company) { List excludeMenuNames = new ArrayList<>(); if (company.getIsSpe() != null && company.getIsSpe() == 2) { excludeMenuNames.addAll(SPE_MENUS); } if (company.getIsTaxi() != null && company.getIsTaxi() == 2) { excludeMenuNames.addAll(TAXI_MENUS); } if (company.getIsCross() != null && company.getIsCross() == 2) { excludeMenuNames.addAll(CROSS_MENUS); } if (company.getIsHitchRide() != null && company.getIsHitchRide() == 2) { excludeMenuNames.addAll(HITCH_RIDE_MENUS); } if (excludeMenuNames.isEmpty()) { return menuList; } menuList.removeIf(node -> excludeMenuNames.contains(node.getName())); return menuList; } }