diff --git a/src/main/java/com/codesdream/ase/component/datamanager/JSONParameter.java b/src/main/java/com/codesdream/ase/component/datamanager/JSONParameter.java index 570c630..7043439 100644 --- a/src/main/java/com/codesdream/ase/component/datamanager/JSONParameter.java +++ b/src/main/java/com/codesdream/ase/component/datamanager/JSONParameter.java @@ -36,7 +36,7 @@ public class JSONParameter { return jsonParam; } - // 根据JSON对象构造JSON字符串用于返回-0= + // 根据JSON对象构造JSON字符串用于返回 public String getJSONString(JSONObject json){ return json.toJSONString(); } @@ -46,4 +46,14 @@ public class JSONParameter { return JSON.toJSONString(object); } + // 由JSON对象获得对应的Java对象 + public T getJavaObject(JSONObject json, Class type){ + return json.toJavaObject(type); + } + + // 由Request获得对应的Java对象(常用于Post请求中) + public T getJavaObjectByRequest(HttpServletRequest request, Class type){ + return getJavaObject(getJSONByRequest(request), type); + } + } diff --git a/src/main/java/com/codesdream/ase/component/permission/ASEAuthenticationFailureHandler.java b/src/main/java/com/codesdream/ase/component/permission/ASEAuthenticationFailureHandler.java new file mode 100644 index 0000000..632a4af --- /dev/null +++ b/src/main/java/com/codesdream/ase/component/permission/ASEAuthenticationFailureHandler.java @@ -0,0 +1,32 @@ +package com.codesdream.ase.component.permission; + +import com.codesdream.ase.component.datamanager.JSONParameter; +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; + +import javax.annotation.Resource; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class ASEAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + @Resource + private JSONParameter jsonParameter; + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) + throws IOException, ServletException + { + logger.info("ASEAuthenticationSuccessHandler Login Fail!"); + UserLoginCheckerRespond respond = new UserLoginCheckerRespond(); + respond.setUserExist(false); + respond.setLoginStatus(false); + response.getWriter().write(jsonParameter.getJSONString(respond)); + } +} diff --git a/src/main/java/com/codesdream/ase/component/permission/ASEAuthenticationSuccessHandler.java b/src/main/java/com/codesdream/ase/component/permission/ASEAuthenticationSuccessHandler.java new file mode 100644 index 0000000..e91adea --- /dev/null +++ b/src/main/java/com/codesdream/ase/component/permission/ASEAuthenticationSuccessHandler.java @@ -0,0 +1,29 @@ +package com.codesdream.ase.component.permission; + +import com.codesdream.ase.component.datamanager.JSONParameter; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class ASEAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { + @Resource + private JSONParameter jsonParameter; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException, ServletException + { + logger.info("ASEAuthenticationSuccessHandler Login Success!"); + UserLoginCheckerRespond respond = new UserLoginCheckerRespond(); + respond.setUserExist(true); + respond.setLoginStatus(true); + response.getWriter().write(jsonParameter.getJSONString(respond)); + } +} diff --git a/src/main/java/com/codesdream/ase/component/permission/ASESecurityAuthenticationProvider.java b/src/main/java/com/codesdream/ase/component/permission/ASESecurityAuthenticationProvider.java index 7092134..243db1b 100644 --- a/src/main/java/com/codesdream/ase/component/permission/ASESecurityAuthenticationProvider.java +++ b/src/main/java/com/codesdream/ase/component/permission/ASESecurityAuthenticationProvider.java @@ -1,5 +1,6 @@ package com.codesdream.ase.component.permission; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.*; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -13,6 +14,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Collection; +@Slf4j @Component public class ASESecurityAuthenticationProvider implements AuthenticationProvider { @Resource @@ -30,7 +32,6 @@ public class ASESecurityAuthenticationProvider implements AuthenticationProvider String username = usernameEncoder.encode(authentication.getName()); // 获得表单中的密码 String password = passwordEncoder.encode(authentication.getCredentials().toString()); - // 判断用户是否存在 UserDetails userInfo = userDetailsService.loadUserByUsername(username); if (userInfo == null) { diff --git a/src/main/java/com/codesdream/ase/component/permission/ASEUnauthorizedEntryPoint.java b/src/main/java/com/codesdream/ase/component/permission/ASEUnauthorizedEntryPoint.java new file mode 100644 index 0000000..9ced87e --- /dev/null +++ b/src/main/java/com/codesdream/ase/component/permission/ASEUnauthorizedEntryPoint.java @@ -0,0 +1,35 @@ +package com.codesdream.ase.component.permission; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Slf4j +@Component +public class ASEUnauthorizedEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) + throws IOException, ServletException + { + + if(isAjaxRequest(request)){ + log.info("IS Ajax Request."); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED,authException.getMessage()); + }else{ + log.info("IS NOT Ajax Request."); + response.sendRedirect("/login"); + } + } + + public static boolean isAjaxRequest(HttpServletRequest request) { + String ajaxFlag = request.getHeader("X-Requested-With"); + return "XMLHttpRequest".equals(ajaxFlag); + } +} diff --git a/src/main/java/com/codesdream/ase/component/permission/ASEUsernamePasswordAuthenticationFilter.java b/src/main/java/com/codesdream/ase/component/permission/ASEUsernamePasswordAuthenticationFilter.java new file mode 100644 index 0000000..e079327 --- /dev/null +++ b/src/main/java/com/codesdream/ase/component/permission/ASEUsernamePasswordAuthenticationFilter.java @@ -0,0 +1,65 @@ +package com.codesdream.ase.component.permission; + +import com.alibaba.fastjson.JSONObject; +import com.codesdream.ase.component.datamanager.JSONParameter; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +import javax.annotation.Resource; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +// 登录验证过滤器 +public class ASEUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + // 常量 + public static final String SPRING_SECURITY_RESTFUL_USERNAME_KEY = "username"; + public static final String SPRING_SECURITY_RESTFUL_PASSWORD_KEY = "password"; + public static final String SPRING_SECURITY_RESTFUL_LOGIN_URL = "/login"; + + private String usernameParameter = SPRING_SECURITY_RESTFUL_USERNAME_KEY; + private String passwordParameter = SPRING_SECURITY_RESTFUL_PASSWORD_KEY; + private boolean postOnly = true; + + @Resource + private JSONParameter jsonParameter; + + protected ASEUsernamePasswordAuthenticationFilter() { + super(new AntPathRequestMatcher(SPRING_SECURITY_RESTFUL_LOGIN_URL, "POST")); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException, ServletException { + // 检查提交方式 + if (postOnly && !request.getMethod().equals("POST")) { + throw new AuthenticationServiceException( + "Authentication Method NOT Supported: " + request.getMethod()); + } + + UserLoginChecker checker = jsonParameter.getJavaObjectByRequest(request, UserLoginChecker.class); + if(!checker.getCheckType().equals("UserLoginChecker")) + throw new AuthenticationServiceException("Invalid Checker Type"); + + String username = checker.getUsername(); + String password = checker.getPassword(); + + if(username == null) username = ""; + if(password == null) password = ""; + + // 去除首尾两端的空白字符 + username = username.trim(); + + UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( + username, password); + + authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); + + return this.getAuthenticationManager().authenticate(authRequest); + } +} diff --git a/src/main/java/com/codesdream/ase/component/permission/UserLoginCheckerRespond.java b/src/main/java/com/codesdream/ase/component/permission/UserLoginCheckerRespond.java index 6a24e6f..59e2fb9 100644 --- a/src/main/java/com/codesdream/ase/component/permission/UserLoginCheckerRespond.java +++ b/src/main/java/com/codesdream/ase/component/permission/UserLoginCheckerRespond.java @@ -8,8 +8,10 @@ import lombok.EqualsAndHashCode; @Data public class UserLoginCheckerRespond extends RespondJSONBaseObject { boolean userExist = false; + boolean loginStatus = false; public UserLoginCheckerRespond(){ super("success"); } + } diff --git a/src/main/java/com/codesdream/ase/controller/ASEErrorController.java b/src/main/java/com/codesdream/ase/controller/ASEErrorController.java index 6e2b7ba..d5930ad 100644 --- a/src/main/java/com/codesdream/ase/controller/ASEErrorController.java +++ b/src/main/java/com/codesdream/ase/controller/ASEErrorController.java @@ -22,18 +22,16 @@ public class ASEErrorController implements ErrorController { public String handleError(HttpServletRequest request, Model model){ Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception"); - // 无效异常检查 - if(statusCode == null || exception == null){ + // 无效异常访问检查 + if(statusCode == null || exception == null) model.addAttribute("if_active", false); - } else { + model.addAttribute("if_active", true); - // 页面未找到 - if (statusCode == HttpStatus.NOT_FOUND.value()) { - return "not_found"; - } + // 检查返回的状态 + if (statusCode == HttpStatus.NOT_FOUND.value()) return "not_found"; model.addAttribute("http_status", statusCode); - // 引发异常检查 + // 检查是否含有引发异常 if (exception.getCause() == null) { model.addAttribute("exception_name", exception.getClass().getName()); model.addAttribute("exception_message", exception.getMessage()); diff --git a/src/main/java/com/codesdream/ase/controller/DataManagerController.java b/src/main/java/com/codesdream/ase/controller/DataManagerController.java index 05c7693..4ca4e7a 100644 --- a/src/main/java/com/codesdream/ase/controller/DataManagerController.java +++ b/src/main/java/com/codesdream/ase/controller/DataManagerController.java @@ -23,7 +23,7 @@ public class DataManagerController { ASESpringUtil springUtil; @RequestMapping(value = "{subSystem}/{dataModel}/query") - private String queryView(Model model, @PathVariable String dataModel, @PathVariable String subSystem) { + public String queryView(Model model, @PathVariable String dataModel, @PathVariable String subSystem) { DataModelRepositorySearcher dataModelRepositorySearcher = springUtil.getBean(DataModelRepositorySearcher.class); DataModelSearcher dataModelSearcher = springUtil.getBean(DataModelSearcher.class); diff --git a/src/main/java/com/codesdream/ase/controller/LoginController.java b/src/main/java/com/codesdream/ase/controller/LoginController.java index 23a14c5..6328f4f 100644 --- a/src/main/java/com/codesdream/ase/controller/LoginController.java +++ b/src/main/java/com/codesdream/ase/controller/LoginController.java @@ -46,12 +46,11 @@ public class LoginController { @RequestMapping(value = "/login/check", method = RequestMethod.POST) @ResponseBody String checkLogin(HttpServletRequest request){ - log.info("Get Login Check Request"); JSONObject json = jsonParameter.getJSONByRequest(request); UserLoginChecker loginChecker = json.toJavaObject(UserLoginChecker.class); // 检查类型 if(loginChecker.getCheckType().equals("UsernameExistChecker")){ - // 计算用户名 + // 根据学号计算用户名 String user = usernameEncoder.encode(loginChecker.getUsername()) ; // 查询用户名存在状态 boolean existStatus = userService.checkIfUserExists(user).getKey(); @@ -59,7 +58,6 @@ public class LoginController { UserLoginCheckerRespond respond = new UserLoginCheckerRespond(); respond.setUserExist(existStatus); return jsonParameter.getJSONString(respond); - } else { // 返回失败对象 diff --git a/src/main/resources/static/assets/js/ase/ase-jquery-framework.js b/src/main/resources/static/assets/js/ase/ase-jquery-framework.js index e17fcd7..23f25fb 100644 --- a/src/main/resources/static/assets/js/ase/ase-jquery-framework.js +++ b/src/main/resources/static/assets/js/ase/ase-jquery-framework.js @@ -53,17 +53,17 @@ function ase_modify_attr(tag, attr_name, attr_value) { } // 修改标签的data-notify属性 -function ase_add_attr_data_notify(tag, value) { +function ase_set_attr_data_notify(tag, value) { ase_modify_attr(tag, 'data-notify', value); } // 修改标签的data-notify-position属性 -function ase_add_attr_data_notify_position(tag, position) { +function ase_set_attr_data_notify_position(tag, position) { ase_modify_attr(tag, 'data-notify-position', position); } // 给标签添加显示值 -function ase_add_show_text(tag, text) { +function ase_set_show_text(tag, text) { tag.html(text); } @@ -78,56 +78,56 @@ function ase_create_tag(tag, id) { } // 给标签指定css属性 -function ase_add_attr_style(tag, value) { +function ase_set_attr_style(tag, value) { ase_modify_attr(tag, 'style', value); } // 给标签指定class属性 -function ase_add_attr_class(tag, value) { +function ase_set_attr_class(tag, value) { ase_modify_attr(tag, 'class', value); } +// 给标签添加class属性 +function ase_add_attr_class(tag, value){ + tag.addClass(value); +} + // 给标签指定class属性 -function ase_add_attr_role(tag, value) { +function ase_set_attr_role(tag, value) { ase_modify_attr(tag, 'role', value); } // 获得一个提示气泡 -function ase_notification_getter() { - const notification = ase_create_tag("div", ase_create_random_id()); - const close_button = ase_create_tag('button'); - const icon_span = ase_create_tag('span'); - const title_span = ase_create_tag('span'); - const message_span = ase_create_tag('span'); - - notification.append(close_button); - notification.append(icon_span); - notification.append(title_span); - notification.append(message_span); - - ase_add_attr_data_notify(notification, 'container'); - ase_add_attr_data_notify_position(notification, 'top-right'); - ase_add_attr_role(notification, 'alert'); - ase_add_attr_class(notification, 'col-10 col-xs-11 col-sm-4 alert alert-danger'); - ase_add_attr_style(notification, 'display: inline-block; ' + - 'margin: 0px auto; ' + - 'padding-left: 65px; ' + - 'position: fixed; ' + - 'transition: all 0.5s ease-in-out 0s; ' + - 'z-index: 1031; ' + - 'top: 254px; ' + - 'right: 20px;'); - - - ase_add_attr_data_notify(close_button, 'dismiss'); - ase_add_attr_data_notify(icon_span, 'icon'); - ase_add_attr_data_notify(title_span, 'title'); - ase_add_attr_data_notify(message_span, 'message'); +function ase_notification(type, title, message) { + $.notify({ + title :title, + message: message + },{ + type: type + }); } +// 将输入框设置为成功 +function ase_set_input_success(input_tag) { + if(input_tag.hasClass("has-error")){ + input_tag.removeClass("has-error"); + } + if(!input_tag.hasClass("has-success")){ + input_tag.addClass("has-success"); + } +} -// 快速给服务器以POST方法传递对象 -function ase_post_object(url, object, callback){ +function ase_set_input_error(input_tag){ + if(input_tag.hasClass("has-success")){ + input_tag.removeClass("has-success"); + } + if(!input_tag.hasClass("has-error")){ + input_tag.addClass("has-error"); + } +} + +// 装饰ajax回调函数 +function callback_decorator(callback){ if(!callback.hasOwnProperty("success")){ ase_debug_log_info("Function Callback NULL") callback.success = function (result) { @@ -143,6 +143,27 @@ function ase_post_object(url, object, callback){ } // 对成功调用返回进行装饰 callback.success = request_success_callback_decorator(callback.success); + return callback; +} + +// 快速以post方式提交表单 +function ase_form_post(url ,id, callback){ + const form = ase_tag_getter("form", id); + callback = callback_decorator(callback); + + $.ajax({ + type: "POST", + dataType: "json", + url: url , + data: form.serialize(), + success: callback.success, + error : callback.error, + }); +} + +// 快速给服务器以POST方法传递对象 +function ase_post_object(url, object, callback){ + callback = callback_decorator(callback); $.ajax({ type: "POST", diff --git a/src/main/resources/static/assets/js/ase/ase-login.js b/src/main/resources/static/assets/js/ase/ase-login.js index 1d94716..65662a0 100644 --- a/src/main/resources/static/assets/js/ase/ase-login.js +++ b/src/main/resources/static/assets/js/ase/ase-login.js @@ -11,6 +11,21 @@ $(document).ready(function () { }); }); +function notify_check() { + ase_notification("danger", "提示", "账号或密码错误"); +} + +function login() { + ase_form_post("/login","login-form", { + success : function (result) { + console.log(result); + }, + error : function (result) { + console.log("FAIL!!!"); + } + }) +} + function check_username(){ const checker = { "checkType": "UsernameExistChecker", @@ -23,20 +38,10 @@ function check_username(){ console.log(result); const usernameGroup = $("div#username-group"); if(result.userExist === true) { - if(usernameGroup.hasClass("has-error")){ - usernameGroup.removeClass("has-error"); - } - if(!usernameGroup.hasClass("has-success")){ - usernameGroup.addClass("has-success"); - } + ase_set_input_success(usernameGroup); } else{ - if(usernameGroup.hasClass("has-success")){ - usernameGroup.removeClass("has-success"); - } - if(!usernameGroup.hasClass("has-error")){ - usernameGroup.addClass("has-error"); - } + ase_set_input_error(usernameGroup); } } }); diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index 5afe640..4f94998 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -20,14 +20,12 @@
-
-
@@ -52,7 +50,7 @@
- +
忘记密码     @@ -61,5 +59,6 @@
+