@@ -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); | |||||
} | |||||
} |
@@ -146,6 +146,7 @@ public class RoleHandler { | |||||
MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id); | MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id); | ||||
if (item == null) return SwListData.create(list, 0); | if (item == null) return SwListData.create(list, 0); | ||||
Menu menu = MenuCache.getInstance().get(item.getMenu()); | Menu menu = MenuCache.getInstance().get(item.getMenu()); | ||||
if (menu == null) return SwListData.create(list, 0); | |||||
ModelForm mf = ModelFormCache.getInstance().get(menu.getPageId()); | ModelForm mf = ModelFormCache.getInstance().get(menu.getPageId()); | ||||
for (String f : menu.getRightSet(SwEnum.MenuRightType.FIELD.value)) { | for (String f : menu.getRightSet(SwEnum.MenuRightType.FIELD.value)) { | ||||
String name = getFieldName(mf, f); | String name = getFieldName(mf, f); | ||||
@@ -180,6 +181,7 @@ public class RoleHandler { | |||||
MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id); | MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id); | ||||
if (item == null) return SwListData.create(list, 0); | if (item == null) return SwListData.create(list, 0); | ||||
Menu menu = MenuCache.getInstance().get(item.getMenu()); | Menu menu = MenuCache.getInstance().get(item.getMenu()); | ||||
if (menu == null) return SwListData.create(list, 0); | |||||
for (String f : menu.getRightSet(SwEnum.MenuRightType.FUNC.value)) { | for (String f : menu.getRightSet(SwEnum.MenuRightType.FUNC.value)) { | ||||
if (PubUtil.isEmpty(f)) continue; | if (PubUtil.isEmpty(f)) continue; | ||||
SwMap row = new SwMap(); | SwMap row = new SwMap(); | ||||
@@ -212,6 +214,7 @@ public class RoleHandler { | |||||
MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id); | MenuPlanItem item = MenuPlanCache.getInstance().getById(role.getSmpId(), mp_id); | ||||
if (item == null) return SwListData.create(list, 0); | if (item == null) return SwListData.create(list, 0); | ||||
Menu menu = MenuCache.getInstance().get(item.getMenu()); | Menu menu = MenuCache.getInstance().get(item.getMenu()); | ||||
if (menu == null) return SwListData.create(list, 0); | |||||
RoleRightContent rc = new RoleRightContent(role.getPrivilege()); | RoleRightContent rc = new RoleRightContent(role.getPrivilege()); | ||||
Map<String, Object> data = rc.getDataRight(item.getId()); | Map<String, Object> data = rc.getDataRight(item.getId()); | ||||
@@ -6,13 +6,20 @@ window.$swEvent.setup("bpm.sys.user.role.roleRight", { | |||||
setup(page) { | setup(page) { | ||||
const {$params, $refs, $widgets, $model, $utils, $tabRouter, $api} = page || {}; | const {$params, $refs, $widgets, $model, $utils, $tabRouter, $api} = page || {}; | ||||
const {$$message, $$http} = $utils || {}; | const {$$message, $$http} = $utils || {}; | ||||
const temp_mp_id = ""; | |||||
// 示例 | // 示例 | ||||
const onBeforeSave = () => { | const onBeforeSave = () => { | ||||
$model.rightData.setFormVal("data", $model.roleDataList.data.list.rows); | $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 { | return { | ||||
onBeforeSave, | onBeforeSave, | ||||
onRoleSelect, | |||||
} | } | ||||
} | } | ||||
}); | }); |
@@ -18,4 +18,7 @@ public interface SwConsts { | |||||
String PARAM_ROWS = "rows"; | String PARAM_ROWS = "rows"; | ||||
String TOTAL_KEY = "total_count"; | String TOTAL_KEY = "total_count"; | ||||
String DEF_DB_NAME = "sys"; | String DEF_DB_NAME = "sys"; | ||||
String LOGIN_VERIFY_CODE = "_VERIFY_CODE"; | |||||
String _LOGIN_USER_ID_IN_SESSION = "_LOGIN_USER_ID_IN_SESSION"; | |||||
} | } |
@@ -1,31 +1,81 @@ | |||||
package cc.smtweb.framework.core.session; | 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.Getter; | ||||
import lombok.Setter; | import lombok.Setter; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpSession; | |||||
import java.io.Serializable; | import java.io.Serializable; | ||||
/** | /** | ||||
* 用户会话缓存,前端调用API时传输 Auto_Token 参数来查找用户会话 | * 用户会话缓存,前端调用API时传输 Auto_Token 参数来查找用户会话 | ||||
* | |||||
* @author xkliu | * @author xkliu | ||||
*/ | */ | ||||
@Getter @Setter | |||||
@Getter | |||||
@Setter | |||||
public class UserSession implements Serializable { | public class UserSession implements Serializable { | ||||
private static final long serialVersionUID = 3854315462714888716L; | private static final long serialVersionUID = 3854315462714888716L; | ||||
// | |||||
private String sessionId = null; //sessionId | |||||
//登录时间 | |||||
private Long loginTimeMillis; | |||||
//最后请求时间 | |||||
private Long lastTimeMillis = 0L; | |||||
//ID | |||||
private String loginIp; | |||||
// 用户ID | // 用户ID | ||||
private long userId; | private long userId; | ||||
// 当前组织ID | |||||
private long companyId; | |||||
// 当前机构ID | |||||
private long partyId; | |||||
// 站点ID | // 站点ID | ||||
private long siteId; | private long siteId; | ||||
// 终端类型 | // 终端类型 | ||||
private byte terminalType; | 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() { | public static UserSession createSys() { | ||||
UserSession us = new UserSession(); | UserSession us = new UserSession(); | ||||
us.userId = 1; | us.userId = 1; | ||||
us.companyId = 1; | |||||
us.partyId = 1; | |||||
us.terminalType = 0; | us.terminalType = 0; | ||||
return us; | |||||
return us; | |||||
} | |||||
public String getUserKey() { | |||||
return userId + "_" + terminalType; | |||||
} | } | ||||
} | } |
@@ -1,12 +1,13 @@ | |||||
package cc.smtweb.framework.core.util; | package cc.smtweb.framework.core.util; | ||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.apache.commons.codec.binary.Base64; | |||||
import org.apache.commons.io.FileUtils; | 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.Charset; | ||||
import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||
@@ -57,4 +58,43 @@ public class FileUtil { | |||||
return null; | 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; | |||||
} | |||||
} | } |