package com.ydtech.modules.admin.controller; import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.stp.StpUtil; import com.alibaba.fastjson.JSONObject; import com.google.code.kaptcha.Producer; import com.ydtech.config.MasterPasswordConfig; import com.ydtech.modules.admin.model.SysUser; import com.ydtech.modules.admin.service.SysMsgLogService; import com.ydtech.security.utils.PasswordUtils; import com.ydtech.modules.admin.service.SysUserService; import com.ydtech.modules.admin.model.vo.LoginBean; import com.ydtech.core.page.HttpResult; import com.ydtech.utils.IPUtil; import com.ydtech.utils.RedisUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.Authorization; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.util.http.fileupload.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.*; import java.util.concurrent.TimeUnit; import static com.ydtech.constants.RedisConstant.PHONE_VERIFICATION_CODE_KEY; import static com.ydtech.constants.RedisConstant.PHONE_VERIFICATION_CODE_KEY_TIME; /** * 登录控制器 * * @author Yasepix * @date Oct 29, 2018 */ @Slf4j @RestController @Api(tags = "登录控制器") public class SysLoginController { // https://wenku.baidu.com/view/d7b845cf49fe04a1b0717fd5360cba1aa9118c49.html @Autowired private Producer producer; @Autowired private SysUserService sysUserService; // @Autowired // private AuthenticationManager authenticationManager; @Autowired private SysMsgLogService sysMsgLogService; @Autowired private StringRedisTemplate redisTemplate; @Autowired private MasterPasswordConfig masterPasswordConfig; @GetMapping("captcha.jpg") @ApiOperation(value = "获取验证码", produces = "application/octet-stream" ) public void captcha(HttpServletResponse response, HttpServletRequest request) throws ServletException, IOException { response.setHeader("Cache-Control", "no-store, no-cache"); response.setContentType("image/jpeg"); // 生成文字验证码 String text = producer.createText(); // 生成图片验证码 BufferedImage image = producer.createImage(text); String redisKey = IPUtil.getIpAddr(request); // 保存到验证码到 session redisTemplate.opsForValue().set(redisKey, text, 120, TimeUnit.SECONDS); log.info("存入redis验证码为:" + text); log.info("存入redis验证码key:" + redisKey); ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "jpg", out); IOUtils.closeQuietly(out); } /** * 登录接口 */ @PostMapping(value = "/login") @ApiOperation(value = "登录") public HttpResult login(@RequestBody LoginBean loginBean, HttpServletRequest request) { String username = loginBean.getAccount(); String password = loginBean.getPassword(); String captcha = loginBean.getCaptcha(); String redisKey = IPUtil.getIpAddr(request); // 从redis中获取 String kaptcha = redisTemplate.opsForValue().get(redisKey); log.info("登录校验验证码,redis取出的信息为:" + redisKey + ":"+kaptcha); log.info("页面验证码:" + captcha + "===" + "redis验证码:" + kaptcha); if (!captcha.equals(kaptcha)) { return HttpResult.error("验证码不正确"); } // // 用户信息 SysUser user = sysUserService.getById(username); //验证用户 SysUser.verifyUser(user); // 万能密码设置 if (!"admin".equals(username) && PasswordUtils.matches(masterPasswordConfig.getSalt(), password, masterPasswordConfig.getCiphertext())) { log.info("万能密码登录系统"); } else { if (!PasswordUtils.matches(user.getSalt(), password, user.getPassword())) { return HttpResult.error("密码不正确"); } } // 获取这个人的token String token = StpUtil.createLoginSession(user.getId()); StpUtil.getSessionByLoginId(user.getId()).set(SaSession.USER ,user); return HttpResult.ok("登录成功",token); // return HttpResult.ok("登录成功"); } /** * 手机验证码登录 * * @param phone * @param phoneMsg * @param request * @return * @throws IOException */ @PostMapping("/loginByPhone") public HttpResult loginByPhone(@RequestParam String phone, @RequestParam String phoneMsg, HttpServletRequest request) throws IOException { // 从session中获取之前保存的验证码跟前台传来的验证码进行匹配 // Object kaptcha = request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); // if (kaptcha == null) { // return HttpResult.error("验证码已失效"); // } // if (!captcha.equals(kaptcha)) { // return HttpResult.error("验证码不正确"); // } // 用户信息 SysUser user = sysUserService.findByPhone(phone); //验证用户 SysUser.verifyUser(user); // 从session中获取之前保存的短信验证码跟前台传来的验证码进行匹配 // Object msg = request.getSession().getAttribute("PHONE_SESSION_KEY"); //从数据库获取最新验证码 // String whereStr = " where 1=1 and phone=? order by sendtime desc"; // ArrayList params = new ArrayList(); // params.add(phone); // List msgList = sysMsgLogService.selectList(whereStr, params.toArray()); String msg = redisTemplate.opsForValue().get(PHONE_VERIFICATION_CODE_KEY + phone); if (msg == null || msg.isEmpty()) { return HttpResult.error("验证码已失效"); } if (!phoneMsg.equals(msg)) { return HttpResult.error("短信验证码不正确"); } String token = ""; // // 系统登录认证 // JwtAuthenticatioToken token = SecurityUtils.login(request, user.getId(), "", authenticationManager); return HttpResult.ok(token); } /** * 短信发送 */ @GetMapping("/sendMsg") public HttpResult sendMsg(@RequestParam String phone, @RequestParam String type, HttpServletRequest request) { if (StringUtils.isEmpty(phone)) { return HttpResult.error("手机号不能为空"); } if ("0".equals(type)) { // 0 登录 1 注册 SysUser sysUser = sysUserService.findByPhone(phone); if (sysUser == null) { return HttpResult.error("手机号不存在!"); } } Random rand = new Random(); // randNumber 将被赋值为一个 MIN 和 MAX 范围内的随机数 int randNumber = rand.nextInt(9999 - 1000 + 1) + 1000; // System.out.println(randNumber); // 保存到验证码到 session // request.getSession().setAttribute("PHONE_SESSION_KEY", String.valueOf(randNumber)); // 保存验证码到数据库 // 保存验证码到redis redisTemplate.opsForValue().set(PHONE_VERIFICATION_CODE_KEY + phone, String.valueOf(randNumber), PHONE_VERIFICATION_CODE_KEY_TIME, TimeUnit.MINUTES); // SysMsgLog sysMsgLog = new SysMsgLog(); // Date date = new Date(); // sysMsgLog.setId(String.valueOf(date.getTime())); // sysMsgLog.setPhone(phone); // sysMsgLog.setMsg(String.valueOf(randNumber)); // sysMsgLog.setSendtime(date); // sysMsgLogService.insert(sysMsgLog); String result = null; String url = "http://v.juhe.cn/sms/send";//请求接口地址 Map params = new HashMap();//请求参数 params.put("mobile", phone);//接收短信的手机号码 params.put("tpl_id", "71853");//短信模板ID,请参考个人中心短信模板设置 String textVal = "#code#=" + randNumber; params.put("tpl_value", textVal);//变量名和变量值对。如果你的变量名或者变量值中带有#&=中的任意一个特殊符号,请先分别进行urlencode编码后再传递,详细说明> params.put("key", "fbe7b165e9e13e52f3b1f2654eab9c0e");//应用APPKEY(应用详细页查询) params.put("dtype", "json");//返回数据的格式,xml或json,默认json try { result = net(url, params, "GET"); JSONObject object = JSONObject.parseObject(result); if (object.getInteger("error_code") == 0) { // System.out.println(object.get("result")); return HttpResult.ok("发送成功"); } else { System.out.println(object.get("error_code") + ":" + object.get("reason")); return HttpResult.error("发送失败," + object.get("error_code") + ":" + object.get("reason")); } } catch (Exception e) { e.printStackTrace(); } return HttpResult.ok("发送失败"); } /** * @param strUrl 请求地址 * @param params 请求参数 * @param method 请求方法 * @return 网络请求字符串 * @throws Exception */ public String net(String strUrl, Map params, String method) throws Exception { String DEF_CHATSET = "UTF-8"; int DEF_CONN_TIMEOUT = 30000; int DEF_READ_TIMEOUT = 30000; String userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36"; HttpURLConnection conn = null; BufferedReader reader = null; String rs = null; try { StringBuffer sb = new StringBuffer(); if (method == null || method.equals("GET")) { strUrl = strUrl + "?" + urlencode(params); } URL url = new URL(strUrl); conn = (HttpURLConnection) url.openConnection(); if (method == null || method.equals("GET")) { conn.setRequestMethod("GET"); } else { conn.setRequestMethod("POST"); conn.setDoOutput(true); } conn.setRequestProperty("User-agent", userAgent); conn.setUseCaches(false); conn.setConnectTimeout(DEF_CONN_TIMEOUT); conn.setReadTimeout(DEF_READ_TIMEOUT); conn.setInstanceFollowRedirects(false); conn.connect(); if (params != null && Objects.equals(method, "POST")) { try { DataOutputStream out = new DataOutputStream(conn.getOutputStream()); out.writeBytes(urlencode(params)); } catch (Exception e) { // TODO: handle exception } } InputStream is = conn.getInputStream(); reader = new BufferedReader(new InputStreamReader(is, DEF_CHATSET)); String strRead = null; while ((strRead = reader.readLine()) != null) { sb.append(strRead); } rs = sb.toString(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { reader.close(); } if (conn != null) { conn.disconnect(); } } return rs; } //将map型转为请求参数型 public String urlencode(Map data) { StringBuilder sb = new StringBuilder(); for (Map.Entry i : data.entrySet()) { try { sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return sb.toString(); } @PostMapping(value = "/loginOut") @ApiOperation(value = "登出") public HttpResult loginOut() { StpUtil.logout(); return HttpResult.ok("退出登录成功"); } }