【网络安全】登录密码加密传输,提高系统安全
This commit is contained in:
parent
0699c2350a
commit
f57c7f85ba
|
|
@ -1,82 +1 @@
|
||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.security.RSAUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
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.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.ConfigService;
import java.util.HashMap;
import java.util.Map;
/**
* 登录验证
*
* @author ruoyi
*/
@Controller
public class SysLoginController extends BaseController
{
/**
* 是否开启记住我功能
*/
@Value("${shiro.rememberMe.enabled: false}")
private boolean rememberMe;
@Autowired
private ConfigService configService;
@GetMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response, ModelMap mmap)
{
// 如果是Ajax请求,返回Json字符串。
if (ServletUtils.isAjaxRequest(request))
{
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
}
// 是否开启记住我
mmap.put("isRemembered", rememberMe);
// 是否开启用户注册
mmap.put("isAllowRegister", Convert.toBool(configService.getKey("sys.account.registerUser"), false));
return "login";
}
@PostMapping("/login")
@ResponseBody
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
{
UsernamePasswordToken token = new UsernamePasswordToken(username, RSAUtils.decryptBase64(password), rememberMe);
Subject subject = SecurityUtils.getSubject();
try
{
subject.login(token);
return success();
}
catch (AuthenticationException e)
{
String msg = "用户或密码错误";
if (StringUtils.isNotEmpty(e.getMessage()))
{
msg = e.getMessage();
}
return error(msg);
}
}
@GetMapping("/unauth")
public String unauth()
{
return "error/unauth";
}
@GetMapping("/getPublicKey")
@ResponseBody
public Map<String, String> getPublicKey() {
Map<String, String> map = new HashMap<>();
map.put("key", RSAUtils.generateBase64PublicKey());
return map;
}
}
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
|
||||||
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.stereotype.Controller;
|
|
||||||
import org.springframework.ui.ModelMap;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
|
||||||
import com.ruoyi.common.core.text.Convert;
|
|
||||||
import com.ruoyi.common.utils.ServletUtils;
|
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
|
||||||
import com.ruoyi.framework.web.service.ConfigService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 登录验证
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
public class SysLoginController extends BaseController
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 是否开启记住我功能
|
|
||||||
*/
|
|
||||||
@Value("${shiro.rememberMe.enabled: false}")
|
|
||||||
private boolean rememberMe;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigService configService;
|
|
||||||
|
|
||||||
@GetMapping("/login")
|
|
||||||
public String login(HttpServletRequest request, HttpServletResponse response, ModelMap mmap)
|
|
||||||
{
|
|
||||||
// 如果是Ajax请求,返回Json字符串。
|
|
||||||
if (ServletUtils.isAjaxRequest(request))
|
|
||||||
{
|
|
||||||
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}");
|
|
||||||
}
|
|
||||||
// 是否开启记住我
|
|
||||||
mmap.put("isRemembered", rememberMe);
|
|
||||||
// 是否开启用户注册
|
|
||||||
mmap.put("isAllowRegister", Convert.toBool(configService.getKey("sys.account.registerUser"), false));
|
|
||||||
return "login";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/login")
|
|
||||||
@ResponseBody
|
|
||||||
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe)
|
|
||||||
{
|
|
||||||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
|
|
||||||
Subject subject = SecurityUtils.getSubject();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
subject.login(token);
|
|
||||||
return success();
|
|
||||||
}
|
|
||||||
catch (AuthenticationException e)
|
|
||||||
{
|
|
||||||
String msg = "用户或密码错误";
|
|
||||||
if (StringUtils.isNotEmpty(e.getMessage()))
|
|
||||||
{
|
|
||||||
msg = e.getMessage();
|
|
||||||
}
|
|
||||||
return error(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/unauth")
|
|
||||||
public String unauth()
|
|
||||||
{
|
|
||||||
return "error/unauth";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -20,16 +20,23 @@ function login() {
|
||||||
var password = $.common.trim($("input[name='password']").val());
|
var password = $.common.trim($("input[name='password']").val());
|
||||||
var validateCode = $("input[name='validateCode']").val();
|
var validateCode = $("input[name='validateCode']").val();
|
||||||
var rememberMe = $("input[name='rememberme']").is(':checked');
|
var rememberMe = $("input[name='rememberme']").is(':checked');
|
||||||
|
var encrypt = new JSEncrypt();
|
||||||
|
$.ajax({
|
||||||
|
url: ctx + "getPublicKey",
|
||||||
|
type: "get",
|
||||||
|
success: function(data) {
|
||||||
|
encrypt.setPublicKey(data.key);
|
||||||
|
var encryptPwd = encrypt.encrypt(password);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "post",
|
type: "post",
|
||||||
url: ctx + "login",
|
url: ctx + "login",
|
||||||
data: {
|
data: {
|
||||||
"username": username,
|
"username": username,
|
||||||
"password": password,
|
"password": encryptPwd,
|
||||||
"validateCode": validateCode,
|
"validateCode": validateCode,
|
||||||
"rememberMe": rememberMe
|
"rememberMe": rememberMe
|
||||||
},
|
},
|
||||||
success: function(r) {
|
success: function (r) {
|
||||||
if (r.code == web_status.SUCCESS) {
|
if (r.code == web_status.SUCCESS) {
|
||||||
location.href = ctx + 'index';
|
location.href = ctx + 'index';
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -40,6 +47,8 @@ function login() {
|
||||||
$.modal.closeLoading();
|
$.modal.closeLoading();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateRule() {
|
function validateRule() {
|
||||||
|
|
|
||||||
|
|
@ -78,5 +78,6 @@
|
||||||
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
|
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
|
||||||
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.8}"></script>
|
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.7.8}"></script>
|
||||||
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
|
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
|
||||||
|
<script src="../static/ajax/libs/security/jsencrypt.min.js" th:src="@{/ajax/libs/security/jsencrypt.min.js}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.ruoyi.common.utils.security;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.security.*;
|
||||||
|
|
||||||
|
public class RSAUtils {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RSAUtils.class);
|
||||||
|
private static KeyPair keyPair = null;
|
||||||
|
|
||||||
|
// 生成秘钥对
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
|
||||||
|
generator.initialize(2048, new SecureRandom());
|
||||||
|
keyPair = generator.generateKeyPair();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
log.error("No such algorithm.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取公钥
|
||||||
|
*
|
||||||
|
* @return 公钥内容
|
||||||
|
*/
|
||||||
|
public static String generateBase64PublicKey() {
|
||||||
|
PublicKey publicKey = keyPair.getPublic();
|
||||||
|
return new String(Base64.encodeBase64(publicKey.getEncoded()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传入字符串用私钥进行解密
|
||||||
|
*
|
||||||
|
* @param string string
|
||||||
|
* @return 解密后的字符串
|
||||||
|
*/
|
||||||
|
public static String decryptBase64(String string) {
|
||||||
|
return new String(decrypt(Base64.decodeBase64(string.getBytes())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] decrypt(byte[] byteArray) {
|
||||||
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
PrivateKey privateKey = keyPair.getPrivate();
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
return cipher.doFinal(byteArray);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -294,6 +294,8 @@ public class ShiroConfig
|
||||||
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
|
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
|
||||||
// 注册相关
|
// 注册相关
|
||||||
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
|
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
|
||||||
|
// 获取公钥
|
||||||
|
filterChainDefinitionMap.put("/getPublicKey", "anon,captchaValidate");
|
||||||
// 系统权限列表
|
// 系统权限列表
|
||||||
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue