Merge remote-tracking branch 'origin/master'

This commit is contained in:
yourtree 2020-03-14 13:17:02 +08:00
commit 47ef733453
18 changed files with 163 additions and 230 deletions

View File

@ -8,6 +8,7 @@ import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
/**
* 处理JSON相关数据
@ -15,25 +16,28 @@ import java.nio.charset.StandardCharsets;
@Component
public class JSONParameter {
// 提取Request中的JSON数据
public JSONObject getJSONByRequest(HttpServletRequest request){
JSONObject jsonParam = null;
// 处理Request Body
public String getRequestBody(HttpServletRequest request){
try {
// 获取输入流
BufferedReader streamReader =
new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
// 写入数据到 String Builder
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = streamReader.readLine()) != null) {
sb.append(line);
}
jsonParam = JSONObject.parseObject(sb.toString());
return request.getParameter("json");
} catch (Exception e) {
e.printStackTrace();
return null;
}
return jsonParam;
}
// 提取Request中的JSON数据
public Optional<JSONObject> getJSONByRequest(HttpServletRequest request){
try {
JSONObject jsonParam = null;
String content = getRequestBody(request);
jsonParam = JSONObject.parseObject(content);
return Optional.ofNullable(jsonParam);
} catch (Exception e) {
e.printStackTrace();
return Optional.empty();
}
}
// 根据JSON对象构造JSON字符串用于返回
@ -52,8 +56,9 @@ public class JSONParameter {
}
// 由Request获得对应的Java对象(常用于Post请求中)
public <T> T getJavaObjectByRequest(HttpServletRequest request, Class<T> type){
return getJavaObject(getJSONByRequest(request), type);
public <T> Optional<T> getJavaObjectByRequest(HttpServletRequest request, Class<T> type){
Optional<JSONObject> json = getJSONByRequest(request);
return json.map(jsonObject -> getJavaObject(jsonObject, type));
}
}

View File

@ -1,20 +0,0 @@
package com.codesdream.ase.component.datamanager;
import lombok.Data;
import java.util.Date;
// 服务端返回的JSON对象模板
@Data
public class RespondJSONBaseObject {
String status = "fail";
Date time = new Date();
public RespondJSONBaseObject(){
}
public RespondJSONBaseObject(String status){
this.status = status;
}
}

View File

@ -1,4 +1,4 @@
package com.codesdream.ase.component.permission;
package com.codesdream.ase.component.json.request;
import lombok.Data;

View File

@ -0,0 +1,9 @@
package com.codesdream.ase.component.json.respond;
// 请求失败返回JSON
public class FailedSONRespond extends JSONBaseRespondObject {
public FailedSONRespond(){
super();
this.status = "fail";
}
}

View File

@ -0,0 +1,22 @@
package com.codesdream.ase.component.json.respond;
import lombok.Data;
import java.util.Date;
// 服务端返回的JSON对象基础信息
@Data
public class JSONBaseRespondObject {
// 请求成功状态
String status = "fail";
// 时间
Date time = new Date();
public JSONBaseRespondObject(){
}
public JSONBaseRespondObject(String status){
this.status = status;
}
}

View File

@ -1,18 +1,18 @@
package com.codesdream.ase.component.permission;
package com.codesdream.ase.component.json.respond;
import com.codesdream.ase.component.datamanager.RespondJSONBaseObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class UserLoginCheckerRespond extends RespondJSONBaseObject {
public class UserLoginCheckerJSONRespond extends JSONBaseRespondObject {
boolean userExist = false;
boolean loginStatus = false;
boolean userBanned = false;
String respondInformation = "";
String sessionId = "";
public UserLoginCheckerRespond(){
public UserLoginCheckerJSONRespond(){
super("success");
}

View File

@ -1,6 +1,7 @@
package com.codesdream.ase.component.permission;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.json.respond.UserLoginCheckerJSONRespond;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
@ -27,7 +28,7 @@ public class ASEAccessDeniedHandler implements AccessDeniedHandler {
response.setCharacterEncoding("utf-8");
response.setContentType("text/javascript;charset=utf-8");
UserLoginCheckerRespond checkerRespond = new UserLoginCheckerRespond();
UserLoginCheckerJSONRespond checkerRespond = new UserLoginCheckerJSONRespond();
checkerRespond.setLoginStatus(true);
checkerRespond.setUserExist(true);
checkerRespond.setRespondInformation("Authenticated user has no access to this resource");

View File

@ -1,6 +1,7 @@
package com.codesdream.ase.component.permission;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.json.respond.UserLoginCheckerJSONRespond;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
@ -26,7 +27,7 @@ public class ASEAuthenticationEntryPoint implements AuthenticationEntryPoint {
response.setCharacterEncoding("utf-8");
response.setContentType("text/javascript;charset=utf-8");
UserLoginCheckerRespond checkerRespond = new UserLoginCheckerRespond();
UserLoginCheckerJSONRespond checkerRespond = new UserLoginCheckerJSONRespond();
checkerRespond.setLoginStatus(false);
checkerRespond.setUserExist(false);
checkerRespond.setUserBanned(true);

View File

@ -1,10 +1,9 @@
package com.codesdream.ase.component.permission;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.json.respond.UserLoginCheckerJSONRespond;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
@ -27,7 +26,7 @@ public class ASEAuthenticationFailureHandler extends SimpleUrlAuthenticationFail
throws IOException, ServletException
{
log.info("ASEAuthenticationSuccessHandler Login Fail!");
UserLoginCheckerRespond respond = new UserLoginCheckerRespond();
UserLoginCheckerJSONRespond respond = new UserLoginCheckerJSONRespond();
respond.setUserExist(false);
respond.setLoginStatus(false);
respond.setUserBanned(true);

View File

@ -1,17 +1,23 @@
package com.codesdream.ase.component.permission;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.json.respond.UserLoginCheckerJSONRespond;
import com.codesdream.ase.model.permission.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;
import java.util.Optional;
// 认证成功返回
@Slf4j
@ -24,12 +30,27 @@ public class ASEAuthenticationSuccessHandler extends SavedRequestAwareAuthentica
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException
{
log.info("ASEAuthenticationSuccessHandler Login Success!");
UserLoginCheckerRespond respond = new UserLoginCheckerRespond();
// 对AJAX登录请求特殊化处理
if(Optional.ofNullable(request.getHeader("X-Requested-With")).isPresent()) {
HttpSession session = request.getSession();
SecurityContext securityContext = SecurityContextHolder.getContext();
session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext);
}
// 打印用户登录成功日志
log.info(String.format("ASEAuthenticationSuccessHandler: %s Login Success.",
((User)authentication.getDetails()).getUsername()));
UserLoginCheckerJSONRespond respond = new UserLoginCheckerJSONRespond();
respond.setUserExist(authentication.isAuthenticated());
respond.setLoginStatus(authentication.isAuthenticated());
// 填充response对象
// 获得session id
WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) (authentication.getDetails());
respond.setSessionId(webAuthenticationDetails.getSessionId());
response.getWriter().write(jsonParameter.getJSONString(respond));
/* response.sendRedirect("/home");*/
}
}

View File

@ -1,29 +1,19 @@
package com.codesdream.ase.component.permission;
import com.alibaba.fastjson.JSONObject;
import com.codesdream.ase.component.datamanager.JSONParameter;
import lombok.Data;
import com.codesdream.ase.component.json.request.UserLoginChecker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.TextEscapeUtils;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Optional;
// 登录验证过滤器
@Slf4j
@ -35,27 +25,31 @@ public class ASEUsernamePasswordAuthenticationFilter extends UsernamePasswordAut
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
// 判断是否为JSON格式的数据
log.info(String.format("Content Type: %s", request.getContentType()));
if(request.getContentType().equals("application/x-www-form-urlencoded; charset=UTF-8")) {
UserLoginChecker checker = jsonParameter.getJavaObjectByRequest(request, UserLoginChecker.class);
if (!checker.getCheckType().equals("From"))
// 判断是否为AJAX请求格式的数据
if(Optional.ofNullable(request.getHeader("X-Requested-With")).isPresent()) {
Optional<UserLoginChecker> checker = jsonParameter.getJavaObjectByRequest(request, UserLoginChecker.class);
if(!checker.isPresent()) throw new BadCredentialsException("Invalid AJAX JSON Request");
if (!checker.get().getCheckType().equals("From"))
throw new AuthenticationServiceException("Invalid Checker Type");
String username = checker.getUsername();
String password = checker.getPassword();
// 获得相应的用户名密码
String username = checker.get().getUsername();
String password = checker.get().getPassword();
if (username == null) username = "";
if (password == null) password = "";
// 去除首尾两端的空白字符
username = username.trim();
password = password.trim();
UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(username, password);
log.info(String.format("User Authentication: %s %s.", username, password));
log.info(String.format("User AJAX JSON Authentication: %s %s.", username, password));
setDetails(request, authRequest);

View File

@ -9,7 +9,15 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.annotation.Resource;
@ -57,7 +65,9 @@ public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
.accessDeniedHandler(accessDeniedHandler);
// 替换掉原有的UsernamePasswordAuthenticationFilter
http.addFilterBefore(usernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
http.addFilterAt(aseUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new SecurityContextPersistenceFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
@ -82,15 +92,30 @@ public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
//注册自定义的UsernamePasswordAuthenticationFilter
@Bean
ASEUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception {
ASEUsernamePasswordAuthenticationFilter aseUsernamePasswordAuthenticationFilter() throws Exception {
ASEUsernamePasswordAuthenticationFilter filter = new ASEUsernamePasswordAuthenticationFilter();
filter.setAuthenticationSuccessHandler(successHandler);
filter.setAuthenticationFailureHandler(failureHandler);
filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy(sessionRegistry()));
filter.setAllowSessionCreation(true);
filter.setRequiresAuthenticationRequestMatcher(
new AntPathRequestMatcher("/login/process", "POST"));
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public SessionAuthenticationStrategy sessionAuthenticationStrategy(SessionRegistry sessionRegistry){
return new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry){{
setMaximumSessions(1);
}};
}
}

View File

@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Controller
public class ActivityController {
@ -48,8 +49,11 @@ public class ActivityController {
if(!webFormValidator.check(activityFormConfigure.getStdActivityForm(), parameterMap)) {
throw new InvalidFormFormatException("Invalid activity form.");
}
JSONObject jsonObject = jsonParameter.getJSONByRequest(request);
Activity activity = jsonObject.toJavaObject(Activity.class);
// 需要检查JSON是否合法
Optional<JSONObject> jsonObject = jsonParameter.getJSONByRequest(request);
if(!jsonObject.isPresent()) return "error";
Activity activity = jsonObject.get().toJavaObject(Activity.class);
NullValueValidator nullValueValidator = aseSpringUtil.getBean(NullValueValidator.class);
List<String> nullValues = nullValueValidator.checkNullValues(activity);
NullValueAttributes nullValueAttributes = aseSpringUtil.getBean(NullValueAttributes.class);

View File

@ -1,18 +1,15 @@
package com.codesdream.ase.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.codesdream.ase.component.datamanager.JSONParameter;
import com.codesdream.ase.component.datamanager.RespondJSONBaseObject;
import com.codesdream.ase.component.json.respond.FailedSONRespond;
import com.codesdream.ase.component.json.respond.JSONBaseRespondObject;
import com.codesdream.ase.component.permission.ASEUsernameEncoder;
import com.codesdream.ase.component.permission.UserLoginChecker;
import com.codesdream.ase.component.permission.UserLoginCheckerRespond;
import com.codesdream.ase.component.json.request.UserLoginChecker;
import com.codesdream.ase.component.json.respond.UserLoginCheckerJSONRespond;
import com.codesdream.ase.service.IUserService;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.sun.org.apache.xpath.internal.operations.Bool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -20,6 +17,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Optional;
/**
@ -46,8 +44,13 @@ public class LoginController {
@RequestMapping(value = "/login/check", method = RequestMethod.POST)
@ResponseBody
String checkLogin(HttpServletRequest request){
JSONObject json = jsonParameter.getJSONByRequest(request);
UserLoginChecker loginChecker = json.toJavaObject(UserLoginChecker.class);
// 检查是否为JSON
Optional<JSONObject> json = jsonParameter.getJSONByRequest(request);
if(!json.isPresent()) return jsonParameter.getJSONString(new FailedSONRespond());
UserLoginChecker loginChecker = json.get().toJavaObject(UserLoginChecker.class);
// 检查类型
if(loginChecker.getCheckType().equals("UsernameExistChecker")){
// 根据学号计算用户名
@ -55,13 +58,13 @@ public class LoginController {
// 查询用户名存在状态
boolean existStatus = userService.checkIfUserExists(user).getKey();
// 构造返回对象
UserLoginCheckerRespond respond = new UserLoginCheckerRespond();
UserLoginCheckerJSONRespond respond = new UserLoginCheckerJSONRespond();
respond.setUserExist(existStatus);
return jsonParameter.getJSONString(respond);
}
else {
// 返回失败对象
return jsonParameter.getJSONString(new RespondJSONBaseObject());
return jsonParameter.getJSONString(new JSONBaseRespondObject());
}
}

View File

@ -18,5 +18,7 @@ spring.datasource.password=codedreampasswd
server.error.whitelabel.enabled=false
logging.level.org.springframework.security=DEBUG
logging.level.root=info
logging.level.org.springframework.security=info
server.servlet.session.timeout=30m

View File

@ -173,7 +173,7 @@ function ase_form_post(url ,id, callback){
type: "POST",
dataType: "json",
url: url ,
data: JSON.stringify(form_object),
data: { json: JSON.stringify(form_object) },
success: callback.success,
error : callback.error,
});
@ -187,7 +187,7 @@ function ase_post_object(url, object, callback){
type: "POST",
dataType: "json",
url: url ,
data: JSON.stringify(object),
data: { json: JSON.stringify(object) },
success: callback.success,
error : callback.error,
});

View File

@ -2,9 +2,8 @@
<html lang="en"
xmlns:th="http://www.thymeleaf.org">
<head>
<div th:include="layout::head"></div>
<meta charset="utf-8">
<title>home</title>
<th:block th:include="layout::head"></th:block>
<title>home</title>
</head>
<body>
@ -375,142 +374,10 @@
<!-- End Sidebar -->
<!-- Custom template | don't include it in your project! --> <!-- End Custom template -->
</div>
<script src="../assets/js/core/jquery.3.2.1.min.js"></script> <script src="../assets/js/core/popper.min.js"></script>
<script src="../assets/js/core/bootstrap.min.js"></script>
<!-- jQuery UI -->
<script src="../assets/js/plugin/jquery-ui-1.12.1.custom/jquery-ui.min.js"></script>
<script src="../assets/js/plugin/jquery-ui-touch-punch/jquery.ui.touch-punch.min.js"></script>
<!-- jQuery Scrollbar -->
<script src="../assets/js/plugin/jquery-scrollbar/jquery.scrollbar.min.js"></script>
<!-- Chart JS -->
<script src="../assets/js/plugin/chart.js/chart.min.js"></script>
<!-- jQuery Sparkline -->
<script src="../assets/js/plugin/jquery.sparkline/jquery.sparkline.min.js"></script>
<!-- Chart Circle -->
<script src="../assets/js/plugin/chart-circle/circles.min.js"></script>
<!-- Datatables -->
<script src="../assets/js/plugin/datatables/datatables.min.js"></script>
<!-- Bootstrap Notify -->
<script src="../assets/js/plugin/bootstrap-notify/bootstrap-notify.min.js"></script>
<!-- jQuery Vector Maps -->
<script src="../assets/js/plugin/jqvmap/jquery.vmap.min.js"></script>
<script src="../assets/js/plugin/jqvmap/maps/jquery.vmap.world.js"></script>
<!-- Sweet Alert -->
<script src="../assets/js/plugin/sweetalert/sweetalert.min.js"></script>
<!-- Atlantis JS -->
<script src="../assets/js/atlantis.min.js"></script>
<!-- Atlantis DEMO methods, don't include it in your project! -->
<script src="../assets/js/setting-demo.js"></script>
<script src="../assets/js/demo.js"></script>
<script>
Circles.create({
id:'circles-1',
radius:45,
value:60,
maxValue:100,
width:7,
text: 5,
colors:['#f1f1f1', '#FF9E27'],
duration:400,
wrpClass:'circles-wrp',
textClass:'circles-text',
styleWrapper:true,
styleText:true
})
Circles.create({
id:'circles-2',
radius:45,
value:70,
maxValue:100,
width:7,
text: 36,
colors:['#f1f1f1', '#2BB930'],
duration:400,
wrpClass:'circles-wrp',
textClass:'circles-text',
styleWrapper:true,
styleText:true
})
Circles.create({
id:'circles-3',
radius:45,
value:40,
maxValue:100,
width:7,
text: 12,
colors:['#f1f1f1', '#F25961'],
duration:400,
wrpClass:'circles-wrp',
textClass:'circles-text',
styleWrapper:true,
styleText:true
})
var totalIncomeChart = document.getElementById('totalIncomeChart').getContext('2d');
var mytotalIncomeChart = new Chart(totalIncomeChart, {
type: 'bar',
data: {
labels: ["S", "M", "T", "W", "T", "F", "S", "S", "M", "T"],
datasets : [{
label: "Total Income",
backgroundColor: '#ff9e27',
borderColor: 'rgb(23, 125, 255)',
data: [6, 4, 9, 5, 4, 6, 4, 3, 8, 10],
}],
},
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false,
},
scales: {
yAxes: [{
ticks: {
display: false //this will remove only the label
},
gridLines : {
drawBorder: false,
display : false
}
}],
xAxes : [ {
gridLines : {
drawBorder: false,
display : false
}
}]
},
}
});
$('#lineChart').sparkline([105,103,123,100,95,105,115], {
type: 'line',
height: '70',
width: '100%',
lineWidth: '2',
lineColor: '#ffa534',
fillColor: 'rgba(255, 165, 52, .14)'
});
</script>
</body>
</html>

View File

@ -17,7 +17,7 @@
<div class="card-header">
<h4 class="card-title">登录</h4>
</div>
<form id="login-form" action="/login/process" method="post">
<form id="login-form" action="/login" method="post">
<div class="card-body">
<div id="username-group" class="form-group">
<label for="username">学号</label>