Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

194
Vistas
Cómo redirigir la aplicación en Struts 2 con Azure SSO

Quiero implementar un SSO con Azure en una aplicación creada con Struts 2, ya implementé el filtro para iniciar sesión desde la página de Microsoft.

ingrese la descripción de la imagen aquí

sin embargo, el problema de la redirección cuando todo es correcto no me queda muy claro, ya que no soy muy bueno con Struts, ya que cuando inicia sesión originalmente en la aplicación, se redirige a una URL como esta localhost:8080/Portal/login/loginAction_validateUser.action .

esta es la clase de inicio de sesión original de la aplicación

 public class ActionLogin extends ActionSupport implements ServletRequestAware { private static Logger logger = LogManager.getLogger(ActionLogin.class); private HttpServletRequest request; private UtilHttp uhttp = new UtilHttp(); private UtilFiles ufiles = new UtilFiles(); private User user; private Person person; private int invalidateSession; public void setServletRequest(HttpServletRequest request) { this.request = request; } public String validateUser() { try { HttpSession session = request.getSession(); uhttp.cleanSession(request); LoginBusiness business = new LoginBusiness(); String page = "menu"; boolean loadMenu = true; if (invalidateSession == 1) { new LoginBusiness().createDifferentSession(session, user.getLogin()); invalidateSession = 0; } user = business.validateUser(user.getLogin(), user.getPassword(), user.getIdProfile()); if (business.isUserLocked(user.getIdUser())) { addActionError(PortalAdministracionErrorCode.E0400.getMessage()); return "blockedAccount"; } if (user.isValidAuth()) { logger.info("user.isValidAuth()"); if (user.isChangePassword()) { loadMenu = false; page = "change"; } if (business.isPasswordExpired(user.getIdUser())) { addActionError(getText(PortalAdministracionErrorCode.E0401.getMessage())); loadMenu = false; return "passwordexpired"; } session = request.getSession(true); session.setAttribute(Constants.SESSION_USER, user); } else { addActionError(getText("label.error.login.password")); user.setAuthType("1"); page = "login"; } return page; } catch (Exception e) { addActionError(e.getMessage()); return "login"; } } public String logOut() { HttpSession session = request.getSession(false); if (session != null) { try { logger.info("Realiza un logOut el usuario "); uhttp.cleanSession(request); return "logout"; //session.invalidate(); } catch (Exception ex) { logger.error(ex); return "logout"; } } return "logout"; } public String invalidateSession() { invalidateSession = 0; return "login"; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public int getInvalidateSession() { return invalidateSession; } public void setInvalidateSession(int invalidateSession) { this.invalidateSession = invalidateSession; } }

este es el xml que esta configurado con struts, cuando el login esta ok redirige al JSP llamado entrada.jsp pero en la url no cambia cuando hace esto si no pone la accion del login que se hizo, alguna idea de como adaptarlo?

mi inicio de sesión.xml

 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="login" namespace="/login" extends="struts-default,json-default"> <interceptors> <interceptor-stack name="defaultSecurityStack"> <interceptor-ref name="tokenSession"> <param name="excludeMethods">*</param> </interceptor-ref> <interceptor-ref name="defaultStack" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="defaultSecurityStack" /> <global-results> <result name="error">/jsp/common/errorDetail.jsp</result> <result name="invalid.token">/jsp/Login.jsp</result> </global-results> <action name="loginAction_*" method="{1}" class="action.ActionLogin"> <result name="login">/jsp/Login.jsp</result> <result name="menu">/jsp/menu/Entrada.jsp</result> <result name="platformAdmon">/jsp/profile/AddPlatformAdmon.jsp</result> <result name="change">/jsp/menu/ChangePassword.jsp</result> <result name="passwordexpired">/jsp/login/account/password-expired.jsp</result> <result name="success">/jsp/menu/ResultOperation.jsp</result> <result name="blockedAccount">/jsp/login/account/blocked.jsp</result> <result name="logout">/jsp/logout.jsp</result> <interceptor-ref name="defaultSecurityStack"> <param name="tokenSession.excludeMethods">validatePlatformAdmin,logOut,editPassword</param> </interceptor-ref> <allowed-methods>toPageLogin, addPlatformAdmon, authType, changePassword, editPassword, logOut, showMenu, validatePlatformAdmin, validateUser</allowed-methods> </action> <action name="account_*" method="{1}" class="com.seguridata.rne.administracion.portal.action.LoginAccountAction"> <result name="login">/jsp/Login.jsp</result> <result name="blocked">/jsp/login/account/blocked.jsp</result> <result name="resultblocked">/jsp/login/account/blocked-response.jsp</result> <result name="unlock">/jsp/login/account/unlock.jsp</result> <result name="resultunlock">/jsp/login/account/unlock-response.jsp</result> <result name="passwordexpired">/jsp/login/account/password-expired.jsp</result> <result name="passwordexpired_success">/jsp/login/account/password-expired-success.jsp</result> <interceptor-ref name="defaultSecurityStack"> <param name="tokenSession.excludeMethods">*</param> </interceptor-ref> <allowed-methods>unlock, unlockRequest, updatePasswordExpired, validateUnlockRequest</allowed-methods> </action> </package> </struts>

este es mi código de filtro para la redirección SSO Realmente no veo el problema aquí pero en la configuración en Azure

 public class BasicFilter implements Filter { public static final String STATES = "states"; public static final String STATE = "state"; public static final Integer STATE_TTL = 3600; public static final String FAILED_TO_VALIDATE_MESSAGE = "Failed to validate data received from Authorization service - "; private String clientId = ""; private String clientSecret = ""; private String tenant = ""; private String authority; public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; if (request instanceof HttpServletRequest) { HttpServletRequest httpRequest = (HttpServletRequest) request; try { String currentUri = httpRequest.getRequestURL().toString(); String queryStr = httpRequest.getQueryString(); String fullUrl = currentUri + (queryStr != null ? "?" + queryStr : ""); // check if user has a AuthData in the session if (!AuthHelper.isAuthenticated(httpRequest)) { if (AuthHelper.containsAuthenticationData(httpRequest)) { processAuthenticationData(httpRequest, currentUri, fullUrl); } else { // not authenticated sendAuthRedirect(httpRequest, httpResponse); return; } } if (isAuthDataExpired(httpRequest)) { updateAuthDataUsingRefreshToken(httpRequest); } } catch (AuthenticationException authException) { // something went wrong (like expiration or revocation of token) // we should invalidate AuthData stored in session and redirect to Authorization server removePrincipalFromSession(httpRequest); sendAuthRedirect(httpRequest, httpResponse); return; } catch (Throwable exc) { httpResponse.setStatus(500); request.setAttribute("error", exc.getMessage()); request.getRequestDispatcher("/error.jsp").forward(request, response); } } chain.doFilter(request, response); } private boolean isAuthDataExpired(HttpServletRequest httpRequest) { AuthenticationResult authData = AuthHelper.getAuthSessionObject(httpRequest); return authData.getExpiresOnDate().before(new Date()) ? true : false; } private void updateAuthDataUsingRefreshToken(HttpServletRequest httpRequest) throws Throwable { AuthenticationResult authData = getAccessTokenFromRefreshToken(AuthHelper.getAuthSessionObject(httpRequest).getRefreshToken()); setSessionPrincipal(httpRequest, authData); } private void processAuthenticationData(HttpServletRequest httpRequest, String currentUri, String fullUrl) throws Throwable { HttpSession session = httpRequest.getSession(false); HashMap<String, String> params = new HashMap<>(); for (String key : httpRequest.getParameterMap().keySet()) { params.put(key, httpRequest.getParameterMap().get(key)[0]); } // validate that state in response equals to state in request StateData stateData = validateState(httpRequest.getSession(), params.get(STATE)); AuthenticationResponse authResponse = AuthenticationResponseParser.parse(new URI(fullUrl), params); if (AuthHelper.isAuthenticationSuccessful(authResponse)) { AuthenticationSuccessResponse oidcResponse = (AuthenticationSuccessResponse) authResponse; // validate that OIDC Auth Response matches Code Flow (contains only requested artifacts) validateAuthRespMatchesCodeFlow(oidcResponse); AuthenticationResult authData = getAccessToken(oidcResponse.getAuthorizationCode(), currentUri); // validate nonce to prevent reply attacks (code maybe substituted to one with broader access) validateNonce(stateData, getClaimValueFromIdToken(authData.getIdToken(), "nonce")); setSessionPrincipal(httpRequest, authData); } else { AuthenticationErrorResponse oidcResponse = (AuthenticationErrorResponse) authResponse; throw new Exception(String.format("Request for auth code failed: %s - %s", oidcResponse.getErrorObject().getCode(), oidcResponse.getErrorObject().getDescription())); } } private void validateNonce(StateData stateData, String nonce) throws Exception { if (StringUtils.isEmpty(nonce) || !nonce.equals(stateData.getNonce())) { throw new Exception(FAILED_TO_VALIDATE_MESSAGE + "could not validate nonce"); } } private String getClaimValueFromIdToken(String idToken, String claimKey) throws ParseException { return (String) JWTParser.parse(idToken).getJWTClaimsSet().getClaim(claimKey); } private void sendAuthRedirect(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException { httpResponse.setStatus(302); // use state parameter to validate response from Authorization server String state = UUID.randomUUID().toString(); // use nonce parameter to validate idToken String nonce = UUID.randomUUID().toString(); storeStateInSession(httpRequest.getSession(), state, nonce); String currentUri = httpRequest.getRequestURL().toString(); httpResponse.sendRedirect(getRedirectUrl(currentUri, state, nonce)); } /** * make sure that state is stored in the session, * delete it from session - should be used only once * * @param session * @param state * @throws Exception */ private StateData validateState(HttpSession session, String state) throws Exception { if (StringUtils.isNotEmpty(state)) { StateData stateDataInSession = removeStateFromSession(session, state); if (stateDataInSession != null) { return stateDataInSession; } } throw new Exception(FAILED_TO_VALIDATE_MESSAGE + "could not validate state"); } private void validateAuthRespMatchesCodeFlow(AuthenticationSuccessResponse oidcResponse) throws Exception { if (oidcResponse.getIDToken() != null || oidcResponse.getAccessToken() != null || oidcResponse.getAuthorizationCode() == null) { throw new Exception(FAILED_TO_VALIDATE_MESSAGE + "unexpected set of artifacts received"); } } @SuppressWarnings("unchecked") private StateData removeStateFromSession(HttpSession session, String state) { Map<String, StateData> states = (Map<String, StateData>) session.getAttribute(STATES); if (states != null) { eliminateExpiredStates(states); StateData stateData = states.get(state); if (stateData != null) { states.remove(state); return stateData; } } return null; } @SuppressWarnings("unchecked") private void storeStateInSession(HttpSession session, String state, String nonce) { if (session.getAttribute(STATES) == null) { session.setAttribute(STATES, new HashMap<String, StateData>()); } ((Map<String, StateData>) session.getAttribute(STATES)).put(state, new StateData(nonce, new Date())); } private void eliminateExpiredStates(Map<String, StateData> map) { Iterator<Map.Entry<String, StateData>> it = map.entrySet().iterator(); Date currTime = new Date(); while (it.hasNext()) { Map.Entry<String, StateData> entry = it.next(); long diffInSeconds = TimeUnit.MILLISECONDS. toSeconds(currTime.getTime() - entry.getValue().getExpirationDate().getTime()); if (diffInSeconds > STATE_TTL) { it.remove(); } } } private AuthenticationResult getAccessTokenFromRefreshToken( String refreshToken) throws Throwable { AuthenticationContext context; AuthenticationResult result = null; ExecutorService service = null; try { service = Executors.newFixedThreadPool(1); context = new AuthenticationContext(authority + tenant + "/", true, service); Future<AuthenticationResult> future = context .acquireTokenByRefreshToken(refreshToken, new ClientCredential(clientId, clientSecret), null, null); result = future.get(); } catch (ExecutionException e) { throw e.getCause(); } finally { service.shutdown(); } if (result == null) { throw new ServiceUnavailableException("authentication result was null"); } return result; } private AuthenticationResult getAccessToken( AuthorizationCode authorizationCode, String currentUri) throws Throwable { String authCode = authorizationCode.getValue(); ClientCredential credential = new ClientCredential(clientId, clientSecret); AuthenticationContext context; AuthenticationResult result = null; ExecutorService service = null; try { service = Executors.newFixedThreadPool(1); context = new AuthenticationContext(authority + tenant + "/", true, service); Future<AuthenticationResult> future = context .acquireTokenByAuthorizationCode(authCode, new URI( currentUri), credential, null); result = future.get(); } catch (ExecutionException e) { throw e.getCause(); } finally { service.shutdown(); } if (result == null) { throw new ServiceUnavailableException("authentication result was null"); } return result; } private void setSessionPrincipal(HttpServletRequest httpRequest, AuthenticationResult result) { httpRequest.getSession().setAttribute(AuthHelper.PRINCIPAL_SESSION_NAME, result); } private void removePrincipalFromSession(HttpServletRequest httpRequest) { httpRequest.getSession().removeAttribute(AuthHelper.PRINCIPAL_SESSION_NAME); } private String getRedirectUrl(String currentUri, String state, String nonce) throws UnsupportedEncodingException { String redirectUrl = authority + this.tenant + "/oauth2/authorize?response_type=code&scope=directory.read.all&response_mode=form_post&redirect_uri=" + URLEncoder.encode(currentUri, "UTF-8") + "&client_id=" + clientId + "&resource=https%3a%2f%2fgraph.microsoft.com" + "&state=" + state + "&nonce=" + nonce; return redirectUrl; } public void init(FilterConfig config) throws ServletException { clientId = config.getInitParameter("client_id"); authority = config.getServletContext().getInitParameter("authority"); tenant = config.getServletContext().getInitParameter("tenant"); clientSecret = config.getInitParameter("secret_key"); } private class StateData { private String nonce; private Date expirationDate; public StateData(String nonce, Date expirationDate) { this.nonce = nonce; this.expirationDate = expirationDate; } public String getNonce() { return nonce; } public Date getExpirationDate() { return expirationDate; } } }

mi web.xml

 <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>struts-prepare</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareFilter</filter-class> </filter> <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class> </filter> <filter> <filter-name>struts-execute</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsExecuteFilter</filter-class> </filter> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts-prepare</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>struts-execute</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <jsp-config> <taglib> <taglib-uri>/struts-tags</taglib-uri> <taglib-location>/WEB-INF/struts-tags.tld</taglib-location> </taglib> <taglib> <taglib-uri>sitemesh-page</taglib-uri> <taglib-location>/WEB-INF/sitemesh-page.tld</taglib-location> </taglib> <taglib> <taglib-uri>sitemesh-decorator</taglib-uri> <taglib-location>/WEB-INF/sitemesh-decorator.tld</taglib-location> </taglib> </jsp-config> <welcome-file-list> <welcome-file>/jsp/Login.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>authority</param-name> <param-value>https://login.windows.net/</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value> </context-param> <context-param> <param-name>tenant</param-name> <param-value>mytenat</param-value> </context-param> <filter-mapping> <filter-name>BasicFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>BasicFilter</filter-name> <filter-class>mx.prototype.adaj4jAzure.BasicFilter</filter-class> <init-param> <param-name>client_id</param-name> <param-value>myclientid</param-value> </init-param> <init-param> <param-name>secret_key</param-name> <param-value>secretkeyy</param-value> </init-param> </filter> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>

mis puntales.xml

 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!-- <constant name="struts.enable.DynamicMethodInvocation" value="true"/> <constant name="struts.devMode" value="false" /> <constant name="struts.configuration.xml.reload" value="false" /> <constant name="struts.i18n.reload" value="false" /> <constant name="struts.custom.i18n.resources" value="ApplicationResources" /> <constant name="struts.multipart.maxSize" value="5242880"/> --> <constant name="struts.enable.DynamicMethodInvocation" value="true"/> <constant name="struts.custom.i18n.resources" value="ApplicationResources" /> <constant name="struts.multipart.maxSize" value="524288000" /> <constant name="struts.devMode" value="false" /> <constant name="struts.i18n.reload" value="false"/> <constant name="struts.configuration.xml.reload" value="false"/> <constant name="struts.freemarker.templatesCache" value="true"/> <constant name="struts.freemarker.templatesCache.updateDelay" value="120"/> <constant name="struts.freemarker.mru.max.strong.size" value="120"/> <constant name="struts.action.excludePattern" value="/struts/webconsole.html" /> <constant name="struts.action.excludePattern" value="/struts/webconsole.css"/> <constant name="struts.action.excludePattern" value="/struts/webconsole.js"/> <include file="strutsDomain.xml"/> <include file="strutsLogin.xml"/> <include file="strutsPasswordParameters.xml"/> <include file="strutsPersonalize.xml"/> <include file="strutsProfile.xml"/> <include file="strutsTemplate.xml"/> <include file="strutsRoute.xml"/> <include file="strutsPlantillas.xml"/> <package name="serveAll" namespace="" extends="struts-default"> <action name="*"> <result>/jsp/common/error.jsp</result> </action> </package> </struts>
over 4 years ago · Santiago Trujillo
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda