From 239573cd0594894c1cb08e51a91c3964df125a72 Mon Sep 17 00:00:00 2001 From: shimingxy Date: Fri, 22 May 2020 15:25:18 +0800 Subject: [PATCH] Authentication Forward Fix Authentication Forward Fix --- .../authn/AbstractAuthenticationProvider.java | 5 ++ ...uestAwareAuthenticationSuccessHandler.java | 85 ++++++++++--------- .../authn/realm/IAuthenticationServer.java | 6 +- .../java/org/maxkey/web/WebConstants.java | 6 +- .../ui/velocity/VelocityEngineFactory.java | 1 - .../velocity/VelocityEngineFactoryBean.java | 1 - .../ui/velocity/VelocityEngineUtils.java | 3 - .../java/org/maxkey/MaxKeyMgtMvcConfig.java | 8 +- .../maxkey/web/endpoint/IndexEndpoint.java | 15 +++- .../maxkey/web/endpoint/LoginEndpoint.java | 25 ++---- .../web/interceptor/PermissionAdapter.java | 31 +++++++ .../src/main/resources/spring/maxkey.xml | 12 +++ .../main/resources/templates/views/index.ftl | 4 +- 13 files changed, 128 insertions(+), 74 deletions(-) diff --git a/maxkey-core/src/main/java/org/maxkey/authn/AbstractAuthenticationProvider.java b/maxkey-core/src/main/java/org/maxkey/authn/AbstractAuthenticationProvider.java index 4f60ee08..4fe47fa3 100644 --- a/maxkey-core/src/main/java/org/maxkey/authn/AbstractAuthenticationProvider.java +++ b/maxkey-core/src/main/java/org/maxkey/authn/AbstractAuthenticationProvider.java @@ -87,6 +87,10 @@ public abstract class AbstractAuthenticationProvider { .getAttribute(WebConstants.CURRENT_LOGIN_USER_PASSWORD_SET_TYPE); // 登录完成后切换SESSION _logger.debug("Login Session {}.", WebContext.getSession().getId()); + + final Object firstSavedRequest = + WebContext.getAttribute(WebConstants.FIRST_SAVED_REQUEST_PARAMETER); + WebContext.getSession().invalidate(); WebContext.setAttribute( WebConstants.CURRENT_USER_SESSION_ID, WebContext.getSession().getId()); @@ -95,6 +99,7 @@ public abstract class AbstractAuthenticationProvider { authenticationRealm.insertLoginHistory( userInfo, ConstantsLoginType.LOCAL, "", "xe00000004", "success"); + WebContext.setAttribute(WebConstants.FIRST_SAVED_REQUEST_PARAMETER,firstSavedRequest); // 认证设置 WebContext.setAuthentication(authentication); WebContext.setUserInfo(userInfo); diff --git a/maxkey-core/src/main/java/org/maxkey/authn/SavedRequestAwareAuthenticationSuccessHandler.java b/maxkey-core/src/main/java/org/maxkey/authn/SavedRequestAwareAuthenticationSuccessHandler.java index 86ee7426..b5f5b46c 100644 --- a/maxkey-core/src/main/java/org/maxkey/authn/SavedRequestAwareAuthenticationSuccessHandler.java +++ b/maxkey-core/src/main/java/org/maxkey/authn/SavedRequestAwareAuthenticationSuccessHandler.java @@ -20,45 +20,47 @@ import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.util.StringUtils; /** - * An authentication success strategy which can make use of the {@link DefaultSavedRequest} which may have been stored in - * the session by the {@link ExceptionTranslationFilter}. When such a request is intercepted and requires authentication, - * the request data is stored to record the original destination before the authentication process commenced, and to - * allow the request to be reconstructed when a redirect to the same URL occurs. This class is responsible for - * performing the redirect to the original URL if appropriate. + * An authentication success strategy which can make use of the + * {@link DefaultSavedRequest} which may have been stored in the session by the + * {@link ExceptionTranslationFilter}. When such a request is intercepted and + * requires authentication, the request data is stored to record the original + * destination before the authentication process commenced, and to allow the + * request to be reconstructed when a redirect to the same URL occurs. This + * class is responsible for performing the redirect to the original URL if + * appropriate. *

- * Following a successful authentication, it decides on the redirect destination, based on the following scenarios: + * Following a successful authentication, it decides on the redirect + * destination, based on the following scenarios: *

* * @author Luke Taylor * @since 3.0 */ -public class SavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { - protected final Logger _logger = LoggerFactory.getLogger(SavedRequestAwareAuthenticationSuccessHandler.class); +public class SavedRequestAwareAuthenticationSuccessHandler + extends SimpleUrlAuthenticationSuccessHandler { + protected final Logger _logger = LoggerFactory.getLogger( + SavedRequestAwareAuthenticationSuccessHandler.class); @Autowired - @Qualifier("remeberMeService") - protected AbstractRemeberMeService remeberMeService; - + @Qualifier("remeberMeService") + protected AbstractRemeberMeService remeberMeService; + private RequestCache requestCache = new HttpSessionRequestCache(); @Override @@ -66,15 +68,18 @@ public class SavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuth Authentication authentication) throws ServletException, IOException { SavedRequest savedRequest = requestCache.getRequest(request, response); - remeberMeService.createRemeberMe(authentication.getPrincipal().toString(), request, response); - + remeberMeService.createRemeberMe( + authentication.getPrincipal().toString(), request, response); + if (savedRequest == null) { super.onAuthenticationSuccess(request, response, authentication); return; } String targetUrlParameter = getTargetUrlParameter(); - if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) { + if (isAlwaysUseDefaultTargetUrl() + || (targetUrlParameter != null + && StringUtils.hasText(request.getParameter(targetUrlParameter)))) { requestCache.removeRequest(request, response); super.onAuthenticationSuccess(request, response, authentication); @@ -82,16 +87,18 @@ public class SavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuth } clearAuthenticationAttributes(request); - + // Use the DefaultSavedRequest URL String targetUrl = savedRequest.getRedirectUrl(); - - //is cas login , with service parameter - logger.info( request.getParameter(WebConstants.CAS_SERVICE_PARAMETER)); - if(request.getParameter(WebConstants.CAS_SERVICE_PARAMETER)!=null && request.getParameter(WebConstants.CAS_SERVICE_PARAMETER).startsWith("http")){ - targetUrl=WebContext.getHttpContextPath()+"/authorize/cas/login?service="+request.getParameter(WebConstants.CAS_SERVICE_PARAMETER); + + // is cas login , with service parameter + logger.info("CAS " + request.getParameter(WebConstants.CAS_SERVICE_PARAMETER)); + if (request.getParameter(WebConstants.CAS_SERVICE_PARAMETER) != null + && request.getParameter(WebConstants.CAS_SERVICE_PARAMETER).startsWith("http")) { + targetUrl = WebContext.getHttpContextPath() + "/authorize/cas/login?service=" + + request.getParameter(WebConstants.CAS_SERVICE_PARAMETER); } - + targetUrl = targetUrl == null ? "/forwardindex" : targetUrl; logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl); getRedirectStrategy().sendRedirect(request, response, targetUrl); } diff --git a/maxkey-core/src/main/java/org/maxkey/authn/realm/IAuthenticationServer.java b/maxkey-core/src/main/java/org/maxkey/authn/realm/IAuthenticationServer.java index a9faa16e..ae709d29 100644 --- a/maxkey-core/src/main/java/org/maxkey/authn/realm/IAuthenticationServer.java +++ b/maxkey-core/src/main/java/org/maxkey/authn/realm/IAuthenticationServer.java @@ -1,14 +1,12 @@ -/** - * - */ package org.maxkey.authn.realm; /** + * IAuthenticationServer . * @author Crystal.Sea * */ public interface IAuthenticationServer { - public boolean authenticate(String username, String password) ; + public boolean authenticate(String username, String password); } diff --git a/maxkey-core/src/main/java/org/maxkey/web/WebConstants.java b/maxkey-core/src/main/java/org/maxkey/web/WebConstants.java index 18baf293..6a04ea67 100644 --- a/maxkey-core/src/main/java/org/maxkey/web/WebConstants.java +++ b/maxkey-core/src/main/java/org/maxkey/web/WebConstants.java @@ -1,7 +1,7 @@ package org.maxkey.web; /** - * Web Application Constants define + * Web Application Constants define. * * @author Crystal.Sea * @@ -32,9 +32,7 @@ public class WebConstants { public static final String CURRENT_MESSAGE = "current_message"; // SPRING_SECURITY_SAVED_REQUEST - public static final String SPRING_PROCESS_SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST"; - - public static final String FIRST_SAVED_REQUEST_PARAMETER = "first_saved_request_parameter"; + public static final String FIRST_SAVED_REQUEST_PARAMETER = "SPRING_SECURITY_SAVED_REQUEST"; public static final String KAPTCHA_SESSION_KEY = "kaptcha_session_key"; diff --git a/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactory.java b/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactory.java index eab9b641..c89cc3cc 100644 --- a/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactory.java +++ b/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactory.java @@ -71,7 +71,6 @@ import org.springframework.util.StringUtils; * @see org.apache.velocity.app.VelocityEngine * @deprecated as of Spring 4.3, in favor of FreeMarker */ -@Deprecated public class VelocityEngineFactory { protected final Log logger = LogFactory.getLog(getClass()); diff --git a/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactoryBean.java b/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactoryBean.java index 7164847d..7c5de1f6 100644 --- a/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactoryBean.java +++ b/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineFactoryBean.java @@ -48,7 +48,6 @@ import org.springframework.context.ResourceLoaderAware; * @see org.springframework.web.servlet.view.velocity.VelocityConfigurer * @deprecated as of Spring 4.3, in favor of FreeMarker */ -@Deprecated public class VelocityEngineFactoryBean extends VelocityEngineFactory implements FactoryBean, InitializingBean, ResourceLoaderAware { diff --git a/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineUtils.java b/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineUtils.java index e5b06aae..7167641d 100644 --- a/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineUtils.java +++ b/maxkey-protocols/maxkey-protocol-saml-2.0/src/main/java/org/springframework/ui/velocity/VelocityEngineUtils.java @@ -32,7 +32,6 @@ import org.apache.velocity.exception.VelocityException; * @since 22.01.2004 * @deprecated as of Spring 4.3, in favor of FreeMarker */ -@Deprecated public abstract class VelocityEngineUtils { /** @@ -46,7 +45,6 @@ public abstract class VelocityEngineUtils { * @deprecated Use {@link #mergeTemplate(VelocityEngine, String, String, Map, Writer)} * instead, following Velocity 1.6's corresponding deprecation in its own API. */ - @Deprecated public static void mergeTemplate( VelocityEngine velocityEngine, String templateLocation, Map model, Writer writer) throws VelocityException { @@ -86,7 +84,6 @@ public abstract class VelocityEngineUtils { * @deprecated Use {@link #mergeTemplateIntoString(VelocityEngine, String, String, Map)} * instead, following Velocity 1.6's corresponding deprecation in its own API. */ - @Deprecated public static String mergeTemplateIntoString(VelocityEngine velocityEngine, String templateLocation, Map model) throws VelocityException { diff --git a/maxkey-web-manage/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java b/maxkey-web-manage/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java index 6d173c22..77615cc2 100644 --- a/maxkey-web-manage/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java +++ b/maxkey-web-manage/src/main/java/org/maxkey/MaxKeyMgtMvcConfig.java @@ -43,16 +43,21 @@ public class MaxKeyMgtMvcConfig implements WebMvcConfigurer { .addPathPatterns("/orgs/**") .addPathPatterns("/userinfo/**") .addPathPatterns("/apps/**") + .addPathPatterns("/app/accounts/**") .addPathPatterns("/groups/**") .addPathPatterns("/groupMember/**") .addPathPatterns("/groupPrivileges/**") + .addPathPatterns("/roles/**") + .addPathPatterns("/rolemembers/**") + .addPathPatterns("/resources/**") + .addPathPatterns("/permissions/**") .addPathPatterns("/config/**") .addPathPatterns("/logs/**") ; + _logger.debug("add PermissionAdapter"); registry.addInterceptor(historyLogsAdapter) - .addPathPatterns("/users/*") .addPathPatterns("/userinfo/**") .addPathPatterns("/enterprises/**") .addPathPatterns("/employees/**") @@ -64,6 +69,7 @@ public class MaxKeyMgtMvcConfig implements WebMvcConfigurer { .addPathPatterns("/approles/**") ; _logger.debug("add HistoryLogsAdapter"); + registry.addInterceptor(localeChangeInterceptor); _logger.debug("add LocaleChangeInterceptor"); diff --git a/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/IndexEndpoint.java b/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/IndexEndpoint.java index 1dea6680..2b6abef4 100644 --- a/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/IndexEndpoint.java +++ b/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/IndexEndpoint.java @@ -1,5 +1,10 @@ package org.maxkey.web.endpoint; +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.maxkey.config.ApplicationConfig; import org.maxkey.constants.ConstantsPasswordSetType; import org.maxkey.domain.UserInfo; @@ -25,9 +30,10 @@ public class IndexEndpoint { @Autowired @Qualifier("applicationConfig") ApplicationConfig applicationConfig; - @RequestMapping(value={"/forwardindex"}) - public ModelAndView forwardindex() { + public ModelAndView forwardindex(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + _logger.debug("IndexEndpoint /forwardindex."); ModelAndView modelAndView=new ModelAndView(); Integer passwordSetType=(Integer)WebContext.getSession().getAttribute(WebConstants.CURRENT_LOGIN_USER_PASSWORD_SET_TYPE); @@ -54,11 +60,14 @@ public class IndexEndpoint { return modelAndView; } + + return new ModelAndView("index"); } @RequestMapping(value={"/index"}) - public ModelAndView home() { + public ModelAndView home(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { _logger.debug("IndexEndpoint /index."); if(applicationConfig.getLoginConfig().getDefaultUri()!=null&& diff --git a/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LoginEndpoint.java b/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LoginEndpoint.java index b2923a34..6753d0c1 100644 --- a/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LoginEndpoint.java +++ b/maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/LoginEndpoint.java @@ -1,7 +1,9 @@ package org.maxkey.web.endpoint; +import java.io.IOException; import java.util.HashMap; +import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -22,9 +24,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.security.web.savedrequest.HttpSessionRequestCache; -import org.springframework.security.web.savedrequest.RequestCache; -import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.ModelAttribute; @@ -148,18 +147,7 @@ public class LoginEndpoint { modelAndView.addObject("ssopList", socialSignOnProviderService.getSocialSignOnProviders()); } } - //save first protected url - SavedRequest firstSavedRequest = (SavedRequest)WebContext.getAttribute(WebConstants.FIRST_SAVED_REQUEST_PARAMETER); - if(firstSavedRequest==null){ - RequestCache requestCache = new HttpSessionRequestCache(); - SavedRequest savedRequest =requestCache.getRequest(request, response); - if(savedRequest!=null){ - _logger.debug("first request parameter "+savedRequest.getRedirectUrl()); - WebContext.setAttribute(WebConstants.FIRST_SAVED_REQUEST_PARAMETER, savedRequest); - } - }else { - WebContext.setAttribute(WebConstants.SPRING_PROCESS_SAVED_REQUEST, firstSavedRequest); - } + if(isAuthenticated){ return WebContext.redirect("/forwardindex"); @@ -169,12 +157,15 @@ public class LoginEndpoint { } @RequestMapping(value={"/logon.do"}) - public ModelAndView logon(@ModelAttribute("authentication") BasicAuthentication authentication) { + public ModelAndView logon( + HttpServletRequest request, + HttpServletResponse response, + @ModelAttribute("authentication") BasicAuthentication authentication) throws ServletException, IOException { authenticationProvider.authenticate(authentication); if(WebContext.isAuthenticated()){ - return WebContext.redirect("/forwardindex"); + return WebContext.redirect("/forwardindex"); }else{ return WebContext.redirect("/login"); } diff --git a/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/PermissionAdapter.java b/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/PermissionAdapter.java index 899cb954..c98bb4ba 100644 --- a/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/PermissionAdapter.java +++ b/maxkey-web-maxkey/src/main/java/org/maxkey/web/interceptor/PermissionAdapter.java @@ -4,12 +4,18 @@ import java.util.concurrent.ConcurrentHashMap; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import org.maxkey.authn.SavedRequestAwareAuthenticationSuccessHandler; import org.maxkey.config.ApplicationConfig; +import org.maxkey.web.WebConstants; import org.maxkey.web.WebContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; +import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /** @@ -26,6 +32,11 @@ public class PermissionAdapter extends HandlerInterceptorAdapter { @Qualifier("applicationConfig") private ApplicationConfig applicationConfig; + + @Autowired + @Qualifier("savedRequestSuccessHandler") + SavedRequestAwareAuthenticationSuccessHandler savedRequestSuccessHandler; + static ConcurrentHashMap navigationsMap = null; /* @@ -41,14 +52,34 @@ public class PermissionAdapter extends HandlerInterceptorAdapter { HttpServletResponse response, Object handler) throws Exception { _logger.trace("PermissionAdapter preHandle"); + //save first protected url + SavedRequest firstSavedRequest = (SavedRequest)WebContext.getAttribute(WebConstants.FIRST_SAVED_REQUEST_PARAMETER); // 判断用户是否登录, 判断用户和角色,判断用户是否登录用户 if (WebContext.getAuthentication() == null || WebContext.getAuthentication().getAuthorities() == null) { + //保存未认证的请求信息 + if(firstSavedRequest==null){ + RequestCache requestCache = new HttpSessionRequestCache(); + requestCache.saveRequest(request, response); + SavedRequest savedRequest =requestCache.getRequest(request, response); + if(savedRequest!=null){ + _logger.debug("first request parameter savedRequest "+savedRequest.getRedirectUrl()); + WebContext.setAttribute(WebConstants.FIRST_SAVED_REQUEST_PARAMETER, savedRequest); + savedRequestSuccessHandler.setRequestCache(requestCache); + } + } + _logger.trace("No Authentication ... forward to /login"); RequestDispatcher dispatcher = request.getRequestDispatcher("/login"); dispatcher.forward(request, response); return false; } + + //认证完成,跳转到未认证请求 + if(firstSavedRequest!=null) { + savedRequestSuccessHandler.onAuthenticationSuccess(request, response, WebContext.getAuthentication()); + WebContext.removeAttribute(WebConstants.FIRST_SAVED_REQUEST_PARAMETER); + } boolean hasAccess = true; diff --git a/maxkey-web-maxkey/src/main/resources/spring/maxkey.xml b/maxkey-web-maxkey/src/main/resources/spring/maxkey.xml index 37d5ba43..09962846 100644 --- a/maxkey-web-maxkey/src/main/resources/spring/maxkey.xml +++ b/maxkey-web-maxkey/src/main/resources/spring/maxkey.xml @@ -185,6 +185,18 @@ + + + + + + + + + + + + diff --git a/maxkey-web-maxkey/src/main/resources/templates/views/index.ftl b/maxkey-web-maxkey/src/main/resources/templates/views/index.ftl index c1f85eca..e164b651 100644 --- a/maxkey-web-maxkey/src/main/resources/templates/views/index.ftl +++ b/maxkey-web-maxkey/src/main/resources/templates/views/index.ftl @@ -3,9 +3,11 @@ MaxKey + + " /> - \ No newline at end of file