
En algunos Bancos que aun siguen le gusta que sus aplicaciones se autentiquen contra su AS400 para así controlar los accesos a los recursos directamente desde este, hoy los quiero mostrar como crear una aplicación Java usando Spring con Spring Security para hacer este simple Login.
Herramientas Utilizadas en el Ejemplo:
- Maven
- Tomcat 8
- Java 8
- Netbeans 8
Ahora si comenzamos, voy a explicar los archivos más importantes, si quieres el código completo lo puedes descargar desde mi Github
El archivo pom.xml
En este archivo coloque todas las dependencias necesarias para usar Spring y Spring Security solo quiero destacar que para usar el api de AS400 coloque la dependencia de esta forma ya que no existe en el repositorio de Maven:
<dependency>
<groupId>com.ibm</groupId>
<artifactId>jt400</artifactId>
<version>6.1.0.6</version>
<scope>system</scope>
<systemPath>${basedir}/lib/jt400.jar</systemPath>
</dependency>
Archivo web.xml
Aquí he configurado el Servlet de Spring y Filtro de Spring Security
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Archivo spring-security.xml
En la configuración se SpringSecurity cree el authenticationProvider el cual usaremos para validar la sesión desde el AS400
<beans:bean id="authenticationProvider"
class="com.stricore.as400.security.CustomAuthenticationProvider">
<beans:property name="nonceValiditySeconds" value="10"/>
<beans:property name="key" value="KEY"/>
</beans:bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="authenticationProvider"/>
</security:authentication-manager>
Archivo login.jsp
Vamos a crear nuestro archivo login.jsp el mismo la vamos a colocar dentro de WEB-INF/pages/auth/login.jsp, para los que no tienen experiencia con Spring Security
<form method="POST" id="form1" name="form1"
action="${pageContext.servletContext.contextPath }/j_spring_security_check"
autocomplete="off">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="hidden" name="timeout" id="timeout" value="${timeout}" />
<c:out value="${message}"/>
<c:if test="${sessionScope.levelerror != null}">
<div id="levelerror " class="error">
<c:out value="${sessionScope.levelerror}" />
<c:remove var="levelerror" scope="session"/>
</div>
</c:if>
<table cellspacing="1">
<tr>
<td>
<label for="signin_username">Usuario</label>
</td>
</tr>
<tr>
<td>
<input id="j_username" name="j_username" type="text" value="" maxlength="10" type="text">
</td>
</tr>
<tr>
<td>
<label for="signin_password">Contraseña</label>
</td>
</tr>
<tr>
<td>
<input id="j_password" name="j_password" type="password" value="" maxlength="10">
</td>
</tr>
<tr>
<td>
<input type="submit" value="Autenticar">
</td>
</tr>
</table>
</form>
Clase AuthController.java
Este es el controlado que va a presentar la pantalla de inicio de sesión:
@Controller
@RequestMapping("/auth")
public class AuthController {
@Autowired
CustomAuthenticationProvider authenticationProvider;
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String getLoginPage(ModelMap model, HttpServletRequest request, HttpSession session) {
String timeout = authenticationProvider.calculateNonce();
session.setAttribute("timeout", timeout);
model.addAttribute("timeout", timeout);
try {
if (request.getParameter("message") != null) {
String message = "";
long error = Long.parseLong(request.getParameter("message"));
if (error == 1) {
message = "Usuario o contraseña no válidos!";
} else if (error == 2) {
message = "Sesión cerrada con éxito";
} else if (error == 3) {
message = "Su sesión expiro!";
} else if (error == 4) {
message = "Su sesión expiro!";
} else if (error == 5) {
message = "Su sesión se ha cerrado por que ha sido abierta desde otro sitio!";
}
request.getSession().setAttribute("levelerror", message);
}
} catch (Exception e) {
}
return "/auth/login";
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String getLogoutPage(ModelMap model, HttpServletRequest request, HttpSession session) {
session.removeAttribute("username");
session.invalidate();
return "/auth/logout";
}
@RequestMapping(value = "/denied", method = RequestMethod.GET)
public String getDeniedPage(@RequestParam(value = "error", required = false) boolean error,
ModelMap model) {
return "/auth/denied";
}
}
Clase CustomAuthenticationProvider.java
En esta clase vamos a iniciar la sesión el AS400, dentro de ella podemos encotrar tres metodos:
authenticate:
@Override
public final Authentication authenticate(Authentication authentication) {
final UsernamePasswordWithTimeoutAuthenticationToken authenticationToken = (UsernamePasswordWithTimeoutAuthenticationToken) authentication;
validateTimeout(authenticationToken);
String name = authentication.getName();
String password = authentication.getCredentials().toString();
if (isPasswordCorrect(authentication)) {
List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
grantedAuths.add(new SimpleGrantedAuthority("superuser"));
Authentication auth = new UsernamePasswordAuthenticationToken(name, password, grantedAuths);
return auth;
} else {
return null;
}
}
isPasswordCorrect: Aquí vamos a iniciar la sesión contra el AS400 con el método validateSignon del jt400.
protected boolean isPasswordCorrect(Authentication authentication) {
String systemName = "PUB1.RZKH.DE";
String userName = authentication.getName();
String userPwd = authentication.getCredentials().toString();
AS400 myAS400 = new AS400(systemName);
String msg = "authentification failed on " + systemName + " for user" + userName;
try {
myAS400.validateSignon(userName, userPwd);
} catch (AS400SecurityException e) {
translateSecurityExceptionAndRethrow(e, userName, systemName);
throw new BadCredentialsException(msg, e);
} catch (IOException e) {
throw new AuthenticationServiceException(msg, e);
}
return true;
}
translateSecurityExceptionAndRethrow: Como el método validateSignon no retorna nada si es correcto, el lanza una excepción de error de autenticación el cual vamos a manjar con este otro método:
private void translateSecurityExceptionAndRethrow(AS400SecurityException e,
String userName, String systemName) {
int code = e.getReturnCode();
String msg = "authentification failed on " + systemName + " for user" + userName;
if (code == AS400SecurityException.PASSWORD_INCORRECT) {
throw new BadCredentialsException(msg, e);
} else if (code == AS400SecurityException.USERID_UNKNOWN) {
throw new UsernameNotFoundException(msg, e);
} else if (code == AS400SecurityException.PASSWORD_EXPIRED) {
throw new CredentialsExpiredException(msg, e);
} else if (code == AS400SecurityException.PASSWORD_INCORRECT_USERID_DISABLE) {
throw new CredentialsExpiredException(msg, e);
} else if (code == AS400SecurityException.USERID_DISABLE) {
throw new CredentialsExpiredException(msg, e);
} else {
throw new BadCredentialsException(msg, e);
}
}
Ahora vamos a correr el proyecto desde Netbeans usando Tomcat:
Y ahora entramos al inicio de sesion:
Descargar el código desde Github también puedes seguirme para que recibas información de todas las soluciones Java con AS400 que voy a seguir montando.
