Browse Source

验证码

master
yaoq 2 years ago
parent
commit
74d44598f5
6 changed files with 290 additions and 10 deletions
  1. +177
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/VerifyCodeController.java
  2. +3
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/role/RoleHandler.java
  3. +8
    -1
      smtweb-framework/bpm/src/main/resources/static/event/bpm/sys/user/role/roleRight.js
  4. +3
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java
  5. +55
    -5
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/UserSession.java
  6. +44
    -4
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/FileUtil.java

+ 177
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/VerifyCodeController.java View File

@@ -0,0 +1,177 @@
package cc.smtweb.system.bpm.spring.controller;

import cc.smtweb.framework.core.common.R;
import cc.smtweb.framework.core.common.SwConsts;
import cc.smtweb.framework.core.util.FileUtil;
import cc.smtweb.framework.core.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

/**
* Created with IntelliJ IDEA.
* User: AKhh
* Date: 12-12-31 上午11:17
* 验证码,放入Session
*/
@Slf4j
@RestController
@RequestMapping("/api")
public class VerifyCodeController {
private final static String CODES = "23456789abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYXZ";

//生成验证码
@RequestMapping(value = "/getVerifyCode")
public void getVerifyCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
setNoCache(response);
// 检验码只有4位长
String code = createCode();
HttpSession session = request.getSession(true);
session.setAttribute(SwConsts.LOGIN_VERIFY_CODE, code); //将验证码写入session;
// 在内存中创建图象
int count = code.length();
int fontSize = 28; //code的字体大小
int fontMargin = fontSize / 18; //字符间隔
int width = 90; //图片长度
int height = 40; //图片高度,根据字体大小自动调整;调整这个系数可以调整字体占图片的比例
int avgWidth = (int) (width / count / 1.2); //字符平均占位宽度
int maxDegree = 26; //最大旋转度数
//生成随机类
ThreadLocalRandom random = ThreadLocalRandom.current();
//背景颜色
Color bkColor = Color.WHITE;
Color bdColor = new Color(220,223,230);

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();

//填充底色为灰白
g.setColor(bkColor);
g.fillRect(0, 0, width, height);

//画边框
g.setColor(bdColor);
g.drawRect(0, 0, width - 1, height - 1);

//画干扰字母、数字
int dSize = (int) (fontSize / 2.5); //调整分母大小以调整干扰字符大小
Font font = new Font("Fixedsys", Font.PLAIN, dSize);
g.setFont(font);
int dNumber = width * height * 2 / dSize / dSize;//根据面积计算干扰字母的个数
for (int i = 0; i < dNumber; i++) {
char d_code = CODES.charAt(random.nextInt(CODES.length()));
g.setColor(getRandColor(100, 150));
g.drawString(String.valueOf(d_code), random.nextInt(width), random.nextInt(height));
}

//开始画验证码:

// 创建字体
font = new Font(Font.MONOSPACED, Font.ITALIC | Font.BOLD, fontSize);
// 设置字体
g.setFont(font);

for (int i = 0; i < count; i++) {
char c = code.charAt(i);
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));//随机选取一种颜色

//随机旋转一个角度[-maxDegre, maxDegree]
int degree = random.nextInt(-maxDegree, maxDegree + 1);

//偏移系数,和旋转角度成反比,以避免字符在图片中越出边框
double offsetFactor = 1 - (Math.abs(degree) / (maxDegree + 1.0));//加上1,避免出现结果为0

g.rotate(degree * Math.PI / 180); //旋转一个角度
int x_bound = avgWidth - fontSize;
if (x_bound < 0) x_bound = 1;
int x = (int) ((fontMargin * (i - 1)) + random.nextInt(x_bound) * offsetFactor) - 8; //横向偏移的距离
int y = (int) (fontSize + random.nextInt(height - fontSize) * offsetFactor); //上下偏移的距离

g.rotate(-degree * Math.PI / 180); //画完一个字符之后,旋转回原来的角度
g.translate(avgWidth, 0);//移动到下一个画画的原点

g.drawString(String.valueOf(c), x, y); //x,y是字符的左下角,偏离原点的距离!!!
//System.out.println(c+": x="+x+" y="+y+" degree="+degree+" offset="+offsetFactor);

//X、Y坐标在合适的范围内随机,不旋转:
//g.drawString(String.valueOf(c), width / count * i + random.nextInt(width / count - fontSize), fontSize + random.nextInt(height - fontSize));
}
g.dispose();
writeResponseJson(response, JsonUtil.encodeString(R.success(FileUtil.imgToBase64(image))));
}

private void writeResponseJson(HttpServletResponse response, String ret) {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0L);
response.setContentType("application/json;charset=UTF-8");
PrintWriter writer = null;
try {
writer = response.getWriter();
writer.write(ret);
writer.flush();
} catch (Exception e) {
log.error("response error", e);
} finally {
if (writer != null) {
writer.close();
}
}
}

private void setNoCache(HttpServletResponse response) {
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
}

//生成验证码内容
private String createCode() {
//生成随机类
Random random = new Random();
// 生成四个随机数
int a = random.nextInt(CODES.length());
int b = random.nextInt(CODES.length());
int c = random.nextInt(CODES.length());
int d = random.nextInt(CODES.length());
StringBuilder sb = new StringBuilder(4);
sb.append(CODES.charAt(a)).append(CODES.charAt(b)).append(CODES.charAt(c)).append(CODES.charAt(d));
return sb.toString();
}

private String createCodeEx() {
//生成随机类
Random random = new Random();
// 生成四个随机数
int a = random.nextInt(10);
int b = random.nextInt(10);
int c = random.nextInt(10);
int d = random.nextInt(10);
StringBuilder sb = new StringBuilder(4);
sb.append(a).append(b).append(c).append(d);
return sb.toString();
}

//给定范围获得随机颜色
private Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255) fc = 255;
if (bc > 255) bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
}

+ 3
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/role/RoleHandler.java View File

@@ -146,6 +146,7 @@ public class RoleHandler {
MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id);
if (item == null) return SwListData.create(list, 0);
Menu menu = MenuCache.getInstance().get(item.getMenu());
if (menu == null) return SwListData.create(list, 0);
ModelForm mf = ModelFormCache.getInstance().get(menu.getPageId());
for (String f : menu.getRightSet(SwEnum.MenuRightType.FIELD.value)) {
String name = getFieldName(mf, f);
@@ -180,6 +181,7 @@ public class RoleHandler {
MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id);
if (item == null) return SwListData.create(list, 0);
Menu menu = MenuCache.getInstance().get(item.getMenu());
if (menu == null) return SwListData.create(list, 0);
for (String f : menu.getRightSet(SwEnum.MenuRightType.FUNC.value)) {
if (PubUtil.isEmpty(f)) continue;
SwMap row = new SwMap();
@@ -212,6 +214,7 @@ public class RoleHandler {
MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id);
if (item == null) return SwListData.create(list, 0);
Menu menu = MenuCache.getInstance().get(item.getMenu());
if (menu == null) return SwListData.create(list, 0);
RoleRightContent rc = new RoleRightContent(role.getPrivilege());
Map<String, Object> data = rc.getDataRight(item.getId());



+ 8
- 1
smtweb-framework/bpm/src/main/resources/static/event/bpm/sys/user/role/roleRight.js View File

@@ -6,13 +6,20 @@ window.$swEvent.setup("bpm.sys.user.role.roleRight", {
setup(page) {
const {$params, $refs, $widgets, $model, $utils, $tabRouter, $api} = page || {};
const {$$message, $$http} = $utils || {};
const temp_mp_id = "";
// 示例
const onBeforeSave = () => {
$model.rightData.setFormVal("data", $model.roleDataList.data.list.rows);
};
const onRoleSelect = (row) => {
if (this.temp_mp_id !== row["srl_id"]) {
$model.menuData.setFormVal("mp_id", "");
}
this.temp_mp_id = row["srl_id"];
}
return {
onBeforeSave,
onRoleSelect,
}
}
});

+ 3
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java View File

@@ -18,4 +18,7 @@ public interface SwConsts {
String PARAM_ROWS = "rows";
String TOTAL_KEY = "total_count";
String DEF_DB_NAME = "sys";

String LOGIN_VERIFY_CODE = "_VERIFY_CODE";
String _LOGIN_USER_ID_IN_SESSION = "_LOGIN_USER_ID_IN_SESSION";
}

+ 55
- 5
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/UserSession.java View File

@@ -1,31 +1,81 @@
package cc.smtweb.framework.core.session;

import cc.smtweb.framework.core.common.SwConsts;
import cc.smtweb.framework.core.util.IpAddrUtil;
import lombok.Getter;
import lombok.Setter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.Serializable;

/**
* 用户会话缓存,前端调用API时传输 Auto_Token 参数来查找用户会话
*
* @author xkliu
*/
@Getter @Setter
@Getter
@Setter
public class UserSession implements Serializable {
private static final long serialVersionUID = 3854315462714888716L;
//
private String sessionId = null; //sessionId
//登录时间
private Long loginTimeMillis;
//最后请求时间
private Long lastTimeMillis = 0L;
//ID
private String loginIp;
// 用户ID
private long userId;
// 当前组织ID
private long companyId;
// 当前机构ID
private long partyId;
// 站点ID
private long siteId;
// 终端类型
private byte terminalType;

public UserSession() {

}

public UserSession(HttpServletRequest request, long user_id) {
this(request, user_id, (byte) 0);
}

public UserSession(HttpServletRequest request, long user_id, byte terminalType) {
this.loginIp = IpAddrUtil.getIpAddr(request);
this.userId = user_id;
this.terminalType = terminalType;

HttpSession session = request.getSession(true);
if (user_id > 0) session.setAttribute(SwConsts._LOGIN_USER_ID_IN_SESSION, getUserKey());
this.sessionId = session.getId();
this.loginTimeMillis = System.currentTimeMillis();
this.lastTimeMillis = this.loginTimeMillis;
}

//模拟
public UserSession(long user_id) {
this(user_id, (byte) 0);

}

public UserSession(long user_id, byte terminalType) {
this.userId = user_id;
this.terminalType = terminalType;
this.loginTimeMillis = System.currentTimeMillis();
}

public static UserSession createSys() {
UserSession us = new UserSession();
us.userId = 1;
us.companyId = 1;
us.partyId = 1;
us.terminalType = 0;
return us;
return us;
}

public String getUserKey() {
return userId + "_" + terminalType;
}
}

+ 44
- 4
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/FileUtil.java View File

@@ -1,12 +1,13 @@
package cc.smtweb.framework.core.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import sun.misc.BASE64Encoder;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

@@ -57,4 +58,43 @@ public class FileUtil {
return null;
}
}


/**
* 将图片转换为base64编码后的字符串
*
* @param path
* @return
* @throws Exception
*/
public static String imgToBase64(String path) throws Exception {
return imgToBase64(new FileInputStream(path));
}

public static String imgToBase64(File file) throws Exception {
return imgToBase64(new FileInputStream(file));
}

public static String imgToBase64(InputStream in) throws Exception {
byte[] data = null;
data = new byte[in.available()];
in.read(data);
in.close();
Base64 encoder = new Base64();
return encoder.encodeAsString(data);
}

public static String imgToBase64(BufferedImage bufferedImage) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
try {
ImageIO.write(bufferedImage, "png", baos);//写入流中
} catch (IOException e) {
e.printStackTrace();
}
byte[] bytes = baos.toByteArray();//转换成字节
BASE64Encoder encoder = new BASE64Encoder();
String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
return "data:image/png;base64," + png_base64;
}
}

Loading…
Cancel
Save