Featured Posts

ExtJS, Spring MVC 3 e Hibernate 3.5: Exemplo de um... Este tutorial demonstra como implementar um CRUD Grid (Create, Read, Update, Delete) usando ExtJS, Spring MVC 3 e Hibernate 3.5 O que geralmente queremos fazer com os dados Create (Criar) - (Insert) Read...

Readmore

ExtJS plugin: PagingToolbarResizer Ei pessoal, Este é o meu primeiro plugin em ExtJS. Apesar de não ser algo complicado, estou muito feliz e é um grande feito para mim! Bem, chega e introduções e vamos ao que realmente interessa. O...

Readmore

8++ perguntas para @loiane - por @hlegius Tempos atrás o Helio me enviou um questionário para eu responder, uma espécie de "entrevista". E agora ele publicou no blog dele! :) São minhas opiniões pessoais, e isso não quer dizer que estou...

Readmore

Carreira em TI: Currículo em Inglês Uma das grandes dificuldades para as pessoas da área de TI é, muitas vezes, escrever um bom currículo em inglês. E ter um currículo em inglês, é essencial, já que inglês é tão importante quanto...

Readmore

Entrevista para o Jornal A Tribuna Jan/2010: Profissões... Na última de semana de janeiro tive a honra de conceder mais uma entrevista para o jornal A Tribuna - vendido no Espírito Santo, meu estado natal - sobre mercado de trabalho na área de TI. A reportagem...

Readmore

Integrando Spring Security com a página de Login do ExtJS

Posted by Loiane | Posted in Ext JS, Spring, Spring Security | Posted on 01-02-2010

2

Esse tutorial irá abordar como configurar o form de login da biblioteca ExtJS (Ajax) ao invés de utilizar a página de login (login.jsp) padrão do Spring Security..

Em vez de usar a página de login do Spring Security, por que não usar um form feito com Ajax?

E como integrar a página de login do ExtJS com o framework Spring Security?

Ok, você já tentou fazer isso, o usuário foi autenticado com sucesso, mas o usuário não é redirecionado para a página principal da aplicação. Como consertar isso?

Não importa de você setou a opção default-target-url no arquivo applicationContext-security.xml, ou setou uma URL para redirecionamento no lado do servidor. Não vai funcionar.

O problema é que o ExtJS faz uma chamada/request Ajax, e nenhum redirecionamento irá funcionar no lado servidor (spring). Você deve fazer esse redirecionamento no lado cliente, que é no código ExtJS/javascript.

Primeiro, você precisa crier o form do login. Você pode utilizar o código de exemplo disponibilizado pelo ExtJS: http://www.extjs.com/learn/Tutorial:Basic_Login e customizá-lo/modificá-lo para funcinoar com o Spring Security.

Se der uma olhada no arquivo login.jsp (padrão do Spring Security), você irá perceber três pontos chaves do form:

  1. URL / form action: j_spring_security_check
  2. Username input name: j_username
  3. Password input name: j_password

É isso que precisa customizar no login do ExtJS para fazê-lo funcinar com o Spring Security. Mas não pense que é assim tão fácil, ainda tem um pequeno detalhe que precisa consertar para funcionar perfeitamente.

O login.js irá ficar assim após as moficações:

Ext.onReady(function(){
	Ext.QuickTips.init();

	// Create a variable to hold our EXT Form Panel.

	// Assign various config options as seen.
	var login = new Ext.FormPanel({
		labelWidth:80,
		url:'j_spring_security_check',
		frame:true,
		title:'Please Login',

		defaultType:'textfield',
		width:300,
		height:150,
		monitorValid:true,
		// Specific attributes for the text fields for username / password.
		// The "name" attribute defines the name of variables sent to the server.

		items:[{
			fieldLabel:'Username',
			name:'j_username',
			allowBlank:false
		},{
			fieldLabel:'Password',

			name:'j_password',
			inputType:'password',
			allowBlank:false
		}],

		// All the magic happens after the user clicks the button
		buttons:[{

			text:'Login',
			formBind: true,
			// Function that fires when user clicks the button
			handler:function(){
			login.getForm().submit({

				method:'POST',

				// Functions that fire (success or failure) when the server responds.
				// The server would actually respond with valid JSON,
				// something like: response.write "{ success: true}" or

				// response.write "{ success: false, errors: { reason: 'Login failed. Try again.' }}"
				// depending on the logic contained within your server script.
				// If a success occurs, the user is notified with an alert messagebox,

				// and when they click "OK", they are redirected to whatever page
				// you define as redirect.

				success:function(){
				Ext.Msg.alert('Status', 'Login Successful!', function(btn, text){

					if (btn == 'ok'){
						window.location = 'main.action';
					}
				});

			},

			// Failure function, see comment above re: success and failure.
			// You can see here, if login fails, it throws a messagebox
			// at the user telling him / her as much.

			failure:function(form, action){
				if(action.failureType == 'server'){
					obj = Ext.util.JSON.decode(action.response.responseText);

					Ext.Msg.alert('Login Failed!', obj.errors.reason);
				}else{
					Ext.Msg.alert('Warning!', 'Authentication server is unreachable : ' + action.response.responseText);

				}
				login.getForm().reset();
			}

			});
		}
		}]
	});

	login.render('login');

});

O que está faltando?

É necessário customizar a classe AuthenticationProcessingFilter para o Spring Security executar a ação no login.

Os métodos “onSuccessfulAuthentication” e “onUnsuccessfulAuthentication” precisam retornar algum conteúdo JSON. Se o usuário for autenticado com sucesso, então redireciona-o para a página principal da aplicação, senão, a aplicação irá mostrar uma mensagem de erro.

Essa é a classe MyAuthenticationProcessingFilter customizada:

package com.loiane.security;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;

public class MyAuthenticationProcessingFilter extends AuthenticationProcessingFilter {

	protected void onSuccessfulAuthentication(HttpServletRequest request,
			HttpServletResponse response, Authentication authResult)
	throws IOException {
		super.onSuccessfulAuthentication(request, response, authResult);

		HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response);

		Writer out = responseWrapper.getWriter();

		String targetUrl = determineTargetUrl( request );
		out.write("{success:true, targetUrl : \'" + targetUrl + "\'}");
		out.close();

	}

	protected void onUnsuccessfulAuthentication( HttpServletRequest request,
			HttpServletResponse response, AuthenticationException failed )
	throws IOException {

		HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response);

		Writer out = responseWrapper.getWriter();

		out.write("{ success: false, errors: { reason: 'Login failed. Try again.' }}");
		out.close();

	}

}

E o arquivo applicationContext-security.xml ficará assim:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:security="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">

	<security:global-method-security />

	<security:http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint">
		<security:intercept-url pattern="/index.jsp" filters="none" />
		<security:intercept-url pattern="/*.action" access="ROLE_USER" />
	</security:http>

	<bean id="authenticationProcessingFilter" class="com.loiane.security.MyAuthenticationProcessingFilter">
		<security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
		<property name="defaultTargetUrl" value="/main.html" />
		<property name="authenticationManager" ref="authenticationManager" />
	</bean>

	<security:authentication-manager alias="authenticationManager" />

	<bean id="authenticationProcessingFilterEntryPoint"
		class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
		<property name="loginFormUrl" value="/index.jsp" />
		<property name="forceHttps" value="false" />
	</bean>

    <!--
    Usernames/Passwords are
        rod/koala
        dianne/emu
        scott/wombat
        peter/opal
    These passwords are from spring security app example
    -->
    <security:authentication-provider>
        <security:password-encoder hash="md5"/>
        <security:user-service>
            <security:user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
            <security:user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" />
            <security:user name="scott" password="2b58af6dddbd072ed27ffc86725d7d3a" authorities="ROLE_USER" />
            <security:user name="peter" password="22b5c9accc6e1ba628cedc63a72d57f8" authorities="ROLE_USER" />
	    </security:user-service>
	</security:authentication-provider>
</beans>

Agora irá logar normalmente com o form de login do ExtJS.

Fiz uma pequena aplicação de exemplo. Se desejar, pode fazer o download do meu repositório no GitHub: http://github.com/loiane/spring-security-extjs-login

Bons códigos!

  • Share/Bookmark

Posts Similares

Comments (2)

Seu blog é mto show, muitos tutos interessantes sobre extjs, bacana demais, fiquei conhecendo hoje, estou impressionado.

Parabéns !

Obrigada Diego! :)

Write a comment