1

I´m trying to integrate a JSF web application with Spring Security.

Currently I'm logging in through a method: authenthicating inside this method and redirecting to the destination page based on the user.

Login page(login.xhtml):

 <h:form id="login">
   <h:outputLabel for="email" value="E-mail: "/> 
   <p:inputText id="email" value="#{loginManagedBean.usuario.email}" required="true"/>
   <p:message for="email"/>

   <h:outputLabel for="pass" value="Contraseña: "/>                
   <p:password id="pass" value="#{loginManagedBean.usuario.password}" required="true"/>
   <p:message for="pass"/>

   <!-- <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> -->

   <p:commandButton value="Login" update="@form" action="#{loginManagedBean.autenticar()}"/>
 </h:form>

loginManagedBean.autenticar()(method that authenticates and redirects):

How can I replace this page and method to work with SpringSecurity?

SpringSecurityConfig:

@Override
protected void configure(HttpSecurity http) throws Exception {

    //.csrf() is optional, enabled by default, if using WebSecurityConfigurerAdapter constructor
    // Have to disable it for POST methods:
    // http://stackoverflow.com/a/20608149/1199132
    http.csrf().disable();

    // Logout and redirection:
    // http://stackoverflow.com/a/24987207/1199132
    http
            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .deleteCookies("JSESSIONID")
            .invalidateHttpSession(true)
            .logoutSuccessUrl("/login.xhtml");

    http
            .authorizeRequests()
            //Permit access for all to error and denied views
            .antMatchers("/WEB-INF/errorpages/general.xhtml", "/WEB-INF/errorpages/accessDenied.xhtml", "/WEB-INF/errorpages/expired.html", "/login.xhtml")
            .permitAll()
            // Only access with admin role
            .antMatchers("/admin/**")
            .hasRole("ADMIN")
            //Permit access only for some roles
            .antMatchers("/alumno/**")
            .hasRole("ALUMNO")
            //Permit access only for some roles
            .antMatchers("/profesor/**")
            .hasRole("PROFESOR")
            //If user doesn't have permission, forward him to login page
            .and()
            .formLogin()
            .loginPage("/login.xhtml")
            .usernameParameter("login:email")
            .passwordParameter("login:pass")
            .loginProcessingUrl("/login") //
            .defaultSuccessUrl("/admin/homeAdmin.xhtml")
            .and()
            .exceptionHandling()
            .accessDeniedPage("/WEB-INF/errorpages/accessDenied.xhtml");
}
Leo
  • 115
  • 3
  • 12
  • 1
    Please Don't put all your code here. Just put that code which caused a problem or that part of the code which you don't understand. otherwise, it's too bored to answer. – always-a-learner Jul 15 '17 at 03:40
  • Spring security is configurable over urls. Apart from that, it provides an authentication endpoint, so you might perform a POST to that authentication endpoint (using a plain form and not a JSF one) and once you are logged in, navigate to your application url. – Aritz Jul 17 '17 at 08:09

2 Answers2

3

I'd rather not use JSF for authentication and use a plain HTML form instead (having configured an Authentication Entry Point before):

<form action="#{request.contextPath}/j_spring_security_check"
    method="post">
    <h:panelGrid styleClass="centered tight-grid" columns="2">
        <p:outputLabel>Usuario</p:outputLabel>
        <input type="text" id="username" name="username"
            required="required" />
        <p:outputLabel>Contraseña</p:outputLabel>
        <input type="password" id="password" name="password"
            required="required" />
    </h:panelGrid>
    <h:panelGrid>
        <button type="submit">
            <span class="ui-button-text">Login</span>
        </button>
    </h:panelGrid>
</form>

This will perform a POST to your Spring Security authentication entry point. Then you can use an AuthenticationSuccessHandler or a default target url to redirect to your JSF application, once the user is logged in.

Aritz
  • 30,971
  • 16
  • 136
  • 217
  • Look and feel wise this is not the best solution – Kukeltje Jul 29 '18 at 07:52
  • @Kukeltje, still you can give the inputs PF style classes. The pure JSFish solution would involve implementing a JSF bean for the login process and resend the info to the Spring endpoint. Even if both of theem seem like a bit of hack, I consider this much simpler. – Aritz Jul 29 '18 at 10:07
  • 1
    Yes but you already gave an answer with all that back in 2017 ;-) And the marketing department should not be ignored (and prime-ui can help out here...) – Kukeltje Jul 29 '18 at 10:14
  • For me it was also necessary to supress the form prefixes for the posted form variables by – stacker Dec 13 '18 at 14:46
  • I used this version. For this, I have one question: after login, how could I use the parameters from class "Users", because this
    doesn't use managed beans? On "welcome" page, the welcome message is "Welcome #{users.username}" (exactly like this it is printed). I use the class "Users.java" and it contains the annotations "ManagedBean" and "SessionScoped".
    – Catalin Vladu Sep 18 '19 at 10:29
  • @CatalinVladu just access this info through the spring security context. – Aritz Sep 18 '19 at 10:39
0

Login button action should perform redirection first like this and pass the flow to spring security.

ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
RequestDispatcher dispatcher = ((ServletRequest) context.getRequest()).getRequestDispatcher("/login");
dispatcher.forward((ServletRequest) context.getRequest(), (ServletResponse) context.getResponse());
FacesContext.getCurrentInstance().responseComplete();