Pre Merge pull request !478 from 有酒只欠你/master

This commit is contained in:
有酒只欠你 2023-12-09 13:34:15 +00:00 committed by Gitee
commit 50a6fb557a
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
6 changed files with 166 additions and 176 deletions

View File

@ -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

View File

@ -1,95 +1,104 @@
$(function() { $(function() {
validateKickout(); validateKickout();
validateRule(); validateRule();
$('.imgcode').click(function() { $('.imgcode').click(function() {
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random(); var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
$(".imgcode").attr("src", url); $(".imgcode").attr("src", url);
}); });
}); });
$.validator.setDefaults({ $.validator.setDefaults({
submitHandler: function() { submitHandler: function() {
login(); login();
} }
}); });
function login() { function login() {
$.modal.loading($("#btnSubmit").data("loading")); $.modal.loading($("#btnSubmit").data("loading"));
var username = $.common.trim($("input[name='username']").val()); var username = $.common.trim($("input[name='username']").val());
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');
$.ajax({ var encrypt = new JSEncrypt();
type: "post", $.ajax({
url: ctx + "login", url: ctx + "getPublicKey",
data: { type: "get",
"username": username, success: function(data) {
"password": password, encrypt.setPublicKey(data.key);
"validateCode": validateCode, var encryptPwd = encrypt.encrypt(password);
"rememberMe": rememberMe $.ajax({
}, type: "post",
success: function(r) { url: ctx + "login",
if (r.code == web_status.SUCCESS) { data: {
location.href = ctx + 'index'; "username": username,
} else { "password": encryptPwd,
$('.imgcode').click(); "validateCode": validateCode,
$(".code").val(""); "rememberMe": rememberMe
$.modal.msg(r.msg); },
} success: function (r) {
$.modal.closeLoading(); if (r.code == web_status.SUCCESS) {
} location.href = ctx + 'index';
}); } else {
} $('.imgcode').click();
$(".code").val("");
function validateRule() { $.modal.msg(r.msg);
var icon = "<i class='fa fa-times-circle'></i> "; }
$("#signupForm").validate({ $.modal.closeLoading();
rules: { }
username: { });
required: true }
}, });
password: { }
required: true
} function validateRule() {
}, var icon = "<i class='fa fa-times-circle'></i> ";
messages: { $("#signupForm").validate({
username: { rules: {
required: icon + "请输入您的用户名", username: {
}, required: true
password: { },
required: icon + "请输入您的密码", password: {
} required: true
} }
}) },
} messages: {
username: {
function validateKickout() { required: icon + "请输入您的用户名",
if (getParam("kickout") == 1) { },
layer.alert("<font color='red'>您已在别处登录,请您修改密码或重新登录</font>", { password: {
icon: 0, required: icon + "请输入您的密码",
title: "系统提示" }
}, }
function(index) { })
//关闭弹窗 }
layer.close(index);
if (top != self) { function validateKickout() {
top.location = self.location; if (getParam("kickout") == 1) {
} else { layer.alert("<font color='red'>您已在别处登录,请您修改密码或重新登录</font>", {
var url = location.search; icon: 0,
if (url) { title: "系统提示"
var oldUrl = window.location.href; },
var newUrl = oldUrl.substring(0, oldUrl.indexOf('?')); function(index) {
self.location = newUrl; //关闭弹窗
} layer.close(index);
} if (top != self) {
}); top.location = self.location;
} } else {
} var url = location.search;
if (url) {
function getParam(paramName) { var oldUrl = window.location.href;
var reg = new RegExp("(^|&)" + paramName + "=([^&]*)(&|$)"); var newUrl = oldUrl.substring(0, oldUrl.indexOf('?'));
var r = window.location.search.substr(1).match(reg); self.location = newUrl;
if (r != null) return decodeURI(r[2]); }
return null; }
});
}
}
function getParam(paramName) {
var reg = new RegExp("(^|&)" + paramName + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURI(r[2]);
return null;
} }

View File

@ -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>

View File

@ -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);
}
}
}

View File

@ -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());