[RESOLVIDO] Struts 2 - redirecionar o usuario

4 respostas
J

olá galera!

estou no finalmente de uma aplicação com struts e estou com uma difuculdade...
o sistema tem uma rotina q envia e-mail qnd um cadastro e realizado...
neste e-mail contem uma url para exibir oq foi cadastrado.

qnd o usuario clicar na url o sistema ira verificar se o usuario esta logado...
caso ele não esteja ira redirecionar para a pagina de login... ate ai td bem...
so q qnd ele faz o login ele e redirecionado para a pagina home.jsp
eu queria q ele fosse redirecionado para a pagina do link do e-mail, entenderam?

qual e a melhor maneira de realizar esta tarefa? alguem ja fez isso? help-me! rss

para checar se o usario esta logado criei um interceptor bem simples, veja:
public class AutorizarAcessoInterceptor implements Interceptor {

    private static final String LOGIN = "login-redirect";

    public void destroy() {  }
    public void init() {   }

    public String intercept(ActionInvocation invocation) throws Exception {

        Usuario usr = (Usuario) invocation.getInvocationContext().getSession().get("usuario");

        if (usr == null) {
            return LOGIN;
        }

        return invocation.invoke();
    }
}
declarei o interceptor no meu struts.xml, veja:
<struts>

    <package name="default" extends="struts-default">

        <interceptors>
            <interceptor name="AutorizarAcesso"
                class="br.com.corpus.ccti.app.interceptors.AutorizarAcessoInterceptor" />

            <interceptor-stack name="cctiStack">
                <interceptor-ref name="AutorizarAcesso" />
                <interceptor-ref name="defaultStack" />
            </interceptor-stack>

        </interceptors>

        <default-interceptor-ref name="cctiStack" />
        
        <global-results>
            <result name="login-redirect" type="chain">
                <param name="actionName">redirect-to-login</param>
                <param name="namespace">/login</param>
            </result>
        </global-results>
        
    </package>

</struts>
obs: so tenho isso no struts.xml pois realizo td o mapeamento com convention e annotations do struts, so criei o struts.xml pq não encontrei um logar para declarar os interceptor com annotations =(

repare q declarei um global-result >>> login-redirect q é chamado pelo interceptor e esta mapeado para a action redirect-to-login

veja o redirect-to-login:
@Action(value = "redirect-to-login",
    results = {@Result(name = "redirect", type = "redirectAction",
        location = "login.action",params = {"namespace", "/login"})
    })
    @SkipValidation
    public String redirectToLogin(){ 
        return "redirect";
    }

funciona q uma maravilha... suahsuashahu

e isso aew galera... me deem uma força, rss

4 Respostas

J

Cara, eu faria assim:

Supondo que o usuario tentou entrar em

http://seuhost/suaAplicacao/acaoX.action

Mas nao estava autenticado... Dai, apos entrar com seus dados de autenticacao deve entrar em acaoX.action, correto?

Faz o seguinte:

No teu Interceptor de autenticacao:

...

 if (usr == null) {  
     String acaoTentada = invocation.getInvocationContext().getName();  // retorna o "acaoX"
     invocation.getInvocationContext().getSession().put("acaoInicial",acaoTentada); // joga o "acaoX" para a sessao
     return LOGIN;  
 }  
   
 return invocation.invoke();  
...
Dai, na sua Action de autenticacao (a que recebe login e senha) voce poe um novo "result" para redirecionamento de acao conforme o atributo de sessao "acaoInicial" :
...
     @Result(name = "redirect", type = "redirectAction",  
         location = "${acaoInicial}")  
   ...
Apos verificar que o login e senha sao validos, basta testar se existe o atributo "acaoInicial" no escopo de sessao:
...
if (invocation.getInvocationContext().getSession().containsKey("acaoInicial"))
   return "redirect";
...
Dai, nessa Action voce deve ter um public String getAcaoInicial() que retorna o atributo "acaoInicial" do escopo de sessao:
...
public String getAcaoInicial() {
   return invocation.getInvocationContext().getSession().get("acaoInicial");
}
...

Deu pra entender ou ficou confuso?

J

fala jyoshiriro blz?

eu estava tentando uma solução parecida com a sua… so q fiquei meio assim em usar session…
tava tentando no request…

bem deu qse td certo… so ta faltando um detalhe…
no interceptor eu estou pegando apenas o name da action

invocation.getInvocationContext().getName();

dai td bem… so que na hora de dar o redirect

@Result(name = "redirect", type = "redirectAction", location = "${acaoInicial}")

ele da erro por causa no namespace =(
eu estou utilizando o name space /login
na hora de dar o redirect ele coloca em /login/acaoinicial.action
e da erro no mapeamento =(

vamos supor q eu acessei minhaapp/cadastro/view.action
ele verifica q não esta logado… e redireciona para o login minhaapp/login/login.action
ate aqui td certo…
na hora q eu faço o login e vou ser redirecionado para ação inicial ele usa o ultimo namespace…
dai fica assim minhaapp/login/view.action e da erro…

para resolver isso e so pegar o namespace correto e ja era =)
agora a pergunta como pegar o name space?

J
opa... consegui!!! :D para recuperar o namespace é so usar:
String namespace = invocation.getProxy().getNamespace();

bem vamos a solução completa...
Tecnologia: Struts 2.1.6 (utilizei convention e annotatios para realizar o mapeamento)
Problema:Ao acessar uma url (ex.: [url]http://host/App/cadastro/view.action[/url]) sua aplicação precisa verificar se o usuario esta logado, caso ele não esteja redirecionar para pagina de login.
ao realizar o login ele precisa ser redirecionado para a url inicial.

Solução:

1º - vc deve criar um interceptor. ([url]http://struts.apache.org/2.x/docs/interceptors.html[/url])
public class AutorizarAcessoInterceptor implements Interceptor {

    private static final String LOGIN = "login-redirect";

    public void destroy() {  }
    public void init() {   }

    public String intercept(ActionInvocation invocation) throws Exception {

        // recuperar o usuario da sessão
        Usuario usr = (Usuario) invocation.getInvocationContext().getSession().get("usuario");

        if (usr == null) {
            // recupera o nome e namespace da ação q foi enviada pelo usuario
            String action = invocation.getProxy().getActionName();
            String namespace = invocation.getProxy().getNamespace();

            // seta o nome da acao e o namspace
            invocation.getInvocationContext().getSession().put("url-action", action);
            invocation.getInvocationContext().getSession().put("url-namespace", namespace);

            return LOGIN;
        }
    
        // se o usuario estiver logado continua normalmente =)
        return invocation.invoke();
    }
}
2º - agora devemos declarar o Interceptor. obs: so declarei o interceptor no struts.xml pq não encontrei uma maneira de declarar com annotations =(
<struts>

    <package name="default" extends="struts-default">

        <interceptors>
            <!-- Declarar nome e classe do Interceptor -->
            <interceptor name="AutorizarAcesso"
                class="br.com.corpus.ccti.app.interceptors.AutorizarAcessoInterceptor" />

            <!-- Declarar o Stack -->
            <interceptor-stack name="cctiStack">
                <interceptor-ref name="AutorizarAcesso" />
                <interceptor-ref name="defaultStack" />
            </interceptor-stack>

        </interceptors>
 
        <!-- colocar o Stack como default -->
        <default-interceptor-ref name="cctiStack" />
        
        <!-- declarar um global-result para ser utilizado no retorno do interceptor q criamos -->
        <global-results>
            <result name="login-redirect" type="chain">
                <param name="actionName">redirect-to-login</param>
                <param name="namespace">/login</param>
            </result>
        </global-results>
        
    </package>

[color=red]importante:[/color] se vc estiver usando annotations vc deve colocar a anotação @ParentPackage("nomeDoPackageQueEstaDeclaradoOInterceptor") para que o interceptor seja executado qnd suas actions forem chamadas...

3º - (opcional) repare q no global-result eu declarei uma action name redirect-to-login. eu poderia simplismete encaminhar direto para a pagina de login, porem estou utilizando sitemesh para decorar a app e ele esta decorando a pagina de login, logo coloquei uma nova action com type="redirectAction" para mudar a url e o sitemesh não decora-la. com isso o global-result ira chamar a action redirect-to-login q irá redirecionar para action login.action
@Action(value = "redirect-to-login",
    results = {@Result(name = "redirect", type = "redirectAction",
        location = "login.action",params = {"namespace", "/login"})
    })
    @SkipValidation
    public String redirectToLogin(){
        return "redirect";
    }
4º - na action de login crie 2 metodos para recuperar os parametros q setamos no interceptor.
public String getUrlAction() {
        return (String) ActionContext.getContext().getSession().get("url-action");
    }

    public String getUrlNamespace() {
        return (String) ActionContext.getContext().getSession().get("url-namespace");
    }
5º - e por fim no metodo q realiza a validação do login coloque:
@Action(value = "validate-login",
    results = {
        @Result(name = "home", location = "/WEB-INF/content/home.jsp"),

        @Result(name = "gourl", type = "redirectAction",
            location = "%{urlAction}", params = {"namespace", "%{urlNamespace}"})
    })
    public String validateLogin() {
   
          //aqui entra toda logica para verificar se o usuario esta correto...

          //depois da verificação e so colocar este if
          if (ActionContext.getContext().getSession().containsKey("url-action")){
                    return "gourl";
          }else{
                    return "home";
          }
    }

agora e so testar =)

bem gostaria de agradecer a todos q me deram uma força, pricipalmente ao jyoshiriro

vlw ate a prox. :thumbup:

M

Pessoal, é o seguinte, preciso redirecionar o usuário para a página que ele estava antes de ser solicitado o login.

Segue o código:

struts.xml

<!DOCTYPE struts PUBLIC  Software Foundation//DTD Struts Configuration 2.0//EN" struts.apache.org/dtds/struts-2.1.dtd">
<struts>
	<package name="home-package" extends="struts-default">
		<interceptors>
			<interceptor name="security" class="interceptors.SecurityInterceptor" />
			<interceptor-stack name="securedBasicStack">
				<interceptor-ref name="security" />
				<interceptor-ref name="defaultStack" />
			</interceptor-stack>
		</interceptors>

		<default-interceptor-ref name="securedBasicStack" />
		<default-action-ref name="index" />

		<global-results>
			<result name="authenticate" type="freemarker">/pages/login.ftl</result>
		</global-results>

		<action name="index" class="actions.IndexAction">
			<result name="success" type="freemarker">/pages/index.ftl</result>
		</action>

		<action name="logon" class="actions.LoginAction">
			<result name="redirect" type="redirectAction">${invokedAction}</result>
			<result name="success" type="redirectAction">index</result>
			<result name="failed" type="freemarker">/pages/login.ftl</result>
		</action>
	</package>
</struts>

actions.LoginAction.java

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {

	private String username;

	private String password;

	private Map<String, Object> session = ActionContext.getContext().getSession();

	public String execute() throws Exception {

		User user = UserDAO.find(username, password);

		if (user != null) {

			// put the user in the session
			session.put("user", user);

			// checks whether the user object is in session and redirect the page
			if (session.containsKey("invokedAction")) {
				return "redirect";
			}

			return SUCCESS;
		} else {
			return "authenticate";
		}
	}

	/**
	 * Clears the session removing the user and others objects
	 * 
	 * @return success
	 */
	public String logoff() {
		session.clear();
		return SUCCESS;
	}

	/**
	 * @return Returns the invoked action
	 */
	public String getInvokedAction() {
		return (String) ActionContext.getContext().getSession().get("invokedAction");
	}

	/**
	 * @return Returns the invoked namespace
	 */
	public String getInvokedNamespace() {
		return (String) ActionContext.getContext().getSession().get("invokedNamespace");
	}

	// ... getters and setters

interceptors.SecurityInterceptor.java

import java.util.List;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class SecurityInterceptor extends AbstractInterceptor {

	@Override
	public String intercept(ActionInvocation invocation) throws Exception {

		User user = (User) invocation.getInvocationContext().getSession().get("user");

		if (user == null) { 

			/*
			 * get the invoked action previously and put this in session
			 */
			String invokedAction = invocation.getProxy().getActionName();
			invocation.getInvocationContext().getSession().put("invokedAction", invokedAction);

			/*
			 * get the invoked namespace previously and put this in session
			 */
			String invokedNamespace = invocation.getProxy().getNamespace();
			invocation.getInvocationContext().getSession().put("invokedNamespace", invokedNamespace);

			return "authenticate";
		}

		return invocation.invoke();
	}
}

Não consigo acessar index.action, mesmo após efetuar o login. Ou melhor, o SecurityInterceptor é chamado sempre e a requisição nem chega em LoginAction. Alguém sabe como posso resolver?

Criado 13 de janeiro de 2010
Ultima resposta 4 de jan. de 2011
Respostas 4
Participantes 3