sobota, 15 kwietnia 2017

Zabezpieczanie aplikacji - ciąg dalszy

Ostatnio pisałam o zabezpieczaniu aplikacji za pomocą Spring Security - dzisiaj pora trochę podrasować naszą funkcję logowania.
Jak już wspominałam, Spring Security automatycznie generuje prostą formatkę do logowania - ale jest, hmm, niezbyt piękna:
Najwyższy czas więc dodać jej nieco wdzięku, zwłaszcza, że HTML z taką formatką powstał już jakiś czas temu.



Wedle tutorialu, wystarczy odrobinę zmodyfikować nasz spring-security.xml. Proste? No pewnie.

    <http auto-config="true">
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/index.jsp" access="permitAll" />
        <intercept-url pattern="/register" access="permitAll" />        
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
        <!-- Custom login form -->
        <form-login
            login-page="/login"
            default-target-url="/mycalendars"
            authentication-failure-url="/login?error"
            username-parameter="user"
            password-parameter="pass" />
        <logout logout-success-url="/login?logout" />
    </http>

Otóż... nie do końca. :) Na potrzeby tutorialu zapewne było to wystarczające, ale z taką konfiguracją moja aplikacja wpadała w nieskończoną pętlę przekierowań - a to dlatego, że strona /login była zabezpieczona, ponieważ pasuje jedynie do wzorca "/**". Brakująca linia to:

        <intercept-url pattern="/login" access="permitAll" />        

Świetnie! Aplikacja już wygląda jakby działała. :) Ale chwila... gdzie się podziało ostylowanie?!
Kto by pomyślał, że dostęp do takich zasobów jak CSS też będzie chroniony? A jednak. :) Do konfiguracji dodajemy jeszcze adres, pod którym znajdują się pliki CSS:

        <intercept-url pattern="/css/**" access="permitAll" />

I voilà, wszystko wróciło do normy. Uff.
Jeszcze tylko kilka zmian w pliku login.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<head>
     (...)
</head>

<body>
 <div class="container">
  <form class="form-signin" action="<c:url value='/j_spring_security_check' />" method='POST'>
   <h2 class="form-signin-heading">Please sign in</h2>
   <c:if test="${not empty error}">
    <div class="error">${error}</div>
   </c:if>
   <c:if test="${not empty msg}">
    <div class="msg">${msg}</div>
   </c:if>
   <div class="form-group">
    <label for="inputEmail" class="sr-only">Email address</label> <input type="email" name="user" id="inputEmail"
     class="form-control" placeholder="Email address" required autofocus> <label for="inputPassword"
     class="sr-only">Password</label> <input type="password" name="pass" id="inputPassword" class="form-control"
     placeholder="Password" required>
    <div class="checkbox">
     <label> <input type="checkbox" value="remember-me"> Remember me
     </label>
    </div>
   </div>
   <input class="btn btn-lg btn-primary btn-block" type="submit" name="submit" value="Sign in"/>
   <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
  </form>
  <div class="form-signin">
    <a href="register">Register</a>
  </div>
 </div>
 <!-- /container -->
</body>
</html>

I dodanie kontrolera w Javie (SecurityController.java):

package pl.annieq.iwilldo.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class SecurityController {

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login(
            @RequestParam(value = "error", required = false) String error,
            @RequestParam(value = "logout", required = false) String logout) {
        
        ModelAndView mv = new ModelAndView();
        if (error != null) {
            mv.addObject("error", "Invalid username or password!");
        }
        if (logout != null) {
            mv.addObject("logout", "You're successfully logged out.");
        }
        mv.setViewName("login");
        return mv;
    }
}

I na tym etapie powinno to wszystko zaśmigać. Ale... nie zaśmigało.
Dlaczego?
Po poszperaniu w internecie (pomógł jak zawsze niezawodny StackOverflow) znalazłam przyczynę - używam innej wersji biblioteki Spring Security niż jest zastosowana w tutorialu. Dlatego do mojej konfiguracji muszę dodać jeszcze jedną linię:

    <http auto-config="true">
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/index.jsp" access="permitAll" />
        <intercept-url pattern="/register" access="permitAll" />        
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
        <!-- Custom login form -->
        <form-login
            login-page="/login"
            login-processing-url="/j_spring_security_check"
            default-target-url="/mycalendars"
            authentication-failure-url="/login?error"
            username-parameter="user"
            password-parameter="pass" />
        <logout logout-success-url="/login?logout" />
    </http>

Teraz wreszcie mogę się cieszyć stroną z kalendarzem, zabezpieczoną hasłem. Yay!

Brak komentarzy:

Prześlij komentarz