2011-02-06 40 views
12

Bu güvenlik sürecini projemde uygulamıştım: Spring Security 3 - MVC Integration Tutorial (Part 2).Yay Güvenliği Ajax oturum açma

Sorunum, Ajax tabanlı bir girişe dönüştürmem gerektiğidir. Bu XML'i yalnızca string/JSON'u istemciye iade etmek için uygun hale getirmek için ne yapmam gerekiyor? Sorunun form-login etiketinde olabileceğini anlıyorum.

<?xml version="1.0" encoding="UTF-8"?> 
<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    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-3.0.xsd 
          http://www.springframework.org/schema/security 
          http://www.springframework.org/schema/security/spring-security-3.0.xsd"> 

    <!-- This is where we configure Spring-Security --> 
    <http auto-config="true" use-expressions="true" access-denied-page="/Management/auth/denied" > 

     <intercept-url pattern="/Management/auth/login" access="permitAll"/> 
     <intercept-url pattern="/Management/main/admin" access="hasRole('ROLE_ADMIN')"/> 
     <intercept-url pattern="/Management/main/common" access="hasRole('ROLE_USER')"/> 

     <form-login 
       login-page="/Management/auth/login" 
       authentication-failure-url="/Management/auth/login?error=true" 
       default-target-url="/Management/main/common"/> 

     <logout 
       invalidate-session="true" 
       logout-success-url="/Management/auth/login" 
       logout-url="/Management/auth/logout"/> 

    </http> 

    <!-- Declare an authentication-manager to use a custom userDetailsService --> 
    <authentication-manager> 
      <authentication-provider user-service-ref="customUserDetailsService"> 
        <password-encoder ref="passwordEncoder"/> 
      </authentication-provider> 
    </authentication-manager> 

    <!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database --> 
    <beans:bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/> 

    <!-- A custom service where Spring will retrieve users and their corresponding access levels --> 
    <beans:bean id="customUserDetailsService" class="com.affiliates.service.CustomUserDetailsService"/> 

</beans:beans> 

cevap

19

Bu eski bir yazıdır, ancak "bahar güvenliği ajax girişi" için en iyi sonuçlardan biri olarak ortaya çıkmaktadır, bu yüzden çözümümü paylaşacağımı düşündüm. Spring Security standartlarını izler ve kurulumu oldukça kolaydır, hile güvenlik yapılandırmanızda 2 <http> öğeye sahip olmak, REST/Ajax için bir ve uygulamanın geri kalanı için bir tane (normal HTML sayfaları). <http> 'un göründüğü sıra önemlidir, daha spesifik olandan daha jenerik URL'lere gitmek zorundadır, <http>'un içindeki <url-intercept> öğeleri gibi.

Adım 1: Kurulum iki ayrı <http> sitesindeki

<?xml version="1.0" encoding="UTF-8"?> 
<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    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-3.1.xsd 
     http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

    <!-- a shared request cache is required for multiple http elements --> 
    <beans:bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache" /> 

    <!-- remove security from static resources to avoid going through the security filter chain --> 
    <http pattern="/resources/**" security="none" /> 

    <!-- http config for REST services (AJAX interface) 
    =================================================== --> 
    <http auto-config="true" use-expressions="true" pattern="/rest/**"> 
     <!-- login configuration 
      login-processing-url="/rest/security/login-processing" front-end AJAX requests for authentication POST to this URL 
      login-page="/rest/security/login-page" means "authentication is required" 
      authentication-failure-url="/rest/security/authentication-failure" means "authentication failed, bad credentials or other security exception" 
      default-target-url="/rest/security/default-target" front-end AJAX requests are redirected here after success authentication 
     --> 
     <form-login 
      login-processing-url="/rest/security/login-processing" 
      login-page="/rest/security/login-page" 
      authentication-failure-url="/rest/security/authentication-failure" 
      default-target-url="/rest/security/default-target" 
      always-use-default-target="true" /> 
     <logout logout-url="/rest/security/logout-url" /> 

     <!-- REST services can be secured here, will respond with JSON instead of HTML --> 
     <intercept-url pattern="/rest/calendar/**" access="hasRole('ROLE_USER')" /> 

     <!-- other REST intercept-urls go here --> 

     <!-- end it with a catch all --> 
     <intercept-url pattern="/rest/**" access="isAuthenticated()" /> 

     <!-- reference to the shared request cache --> 
     <request-cache ref="requestCache"/> 
    </http> 

    <!-- http config for regular HTML pages 
    =================================================== --> 
    <http auto-config="true" use-expressions="true"> 
     <form-login 
      login-processing-url="/security/j_spring_security_check" 
      login-page="/login" 
      authentication-failure-url="/login?login_error=t" /> 
     <logout logout-url="/security/j_spring_security_logout" /> 

     <intercept-url pattern="/calendar/**" access="hasRole('ROLE_USER')" /> 

     <!-- other intercept-urls go here --> 

     <!-- in my app's case, the HTML config ends with permitting all users and requiring HTTPS 
      it is always a good idea to send sensitive information like passwords over HTTPS --> 
     <intercept-url pattern="/**" access="permitAll" requires-channel="https" /> 

     <!-- reference to the shared request cache --> 
     <request-cache ref="requestCache"/> 
    </http> 

    <!-- authentication manager and other configuration go below --> 
</beans:beans> 

Adım 2: İstirahat Doğrulama Kontrol

import org.springframework.http.HttpHeaders; 
import org.springframework.http.HttpStatus; 
import org.springframework.http.ResponseEntity; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.context.SecurityContextHolder; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

import flexjson.JSONSerializer; 

@Controller 
@RequestMapping(value = "/rest/security") 
public class RestAuthenticationController { 

    public HttpHeaders getJsonHeaders() { 
     HttpHeaders headers = new HttpHeaders(); 
     headers.add("Content-Type", "application/json"); 
     return headers; 
    } 

    @RequestMapping(value="/login-page", method = RequestMethod.GET) 
    public ResponseEntity<String> apiLoginPage() { 
     return new ResponseEntity<String>(getJsonHeaders(), HttpStatus.UNAUTHORIZED); 
    } 

    @RequestMapping(value="/authentication-failure", method = RequestMethod.GET) 
    public ResponseEntity<String> apiAuthenticationFailure() { 
     // return HttpStatus.OK to let your front-end know the request completed (no 401, it will cause you to go back to login again, loops, not good) 
     // include some message code to indicate unsuccessful login 
     return new ResponseEntity<String>("{\"success\" : false, \"message\" : \"authentication-failure\"}", getJsonHeaders(), HttpStatus.OK); 
    } 

    @RequestMapping(value="/default-target", method = RequestMethod.GET) 
    public ResponseEntity<String> apiDefaultTarget() { 
     Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 
     // exclude/include whatever fields you need 
     String userJson = new JSONSerializer().exclude("*.class", "*.password").serialize(authentication); 
     return new ResponseEntity<String>(userJson, getJsonHeaders(), HttpStatus.OK); 
    } 
} 

Adım 3: AJAX formu gönder ve tepki işlem, gerekli jQuery adlı kullanıcının ajaxForm kütüphanesi

<form action="/rest/security/login-processing" method="POST"> 
... 
</form> 

$('form').ajaxForm({ 
    success: function(response, statusText, xhr, $form) { 
     console.log(response); 
     if(response == null || response.username == null) { 
      alert("authentication failure"); 
     } else { 
      // response is JSON version of the Spring's Authentication 
      alert("authentication success"); 
     } 
    }, 
    error: function(response, statusText, error, $form) { 
     if(response != null && response.message == "authentication-failure") { 
      alert("authentication failure"); 
     } 
    } 
}); 
+0

Çözümünüz güzel görünüyor ama burada 'için/dinlenme/güvenlik/giriş-işleme" tanımlı –

+0

@MichaelDeKeyser yanıt kontrolör yöntemidir? - o SpringSecurity tarafından sağlanan UsernamePasswordAuthenticationFilter eşlenmiş, dokümanlar ve arama bakmak 'UsernamePasswordAuthenticationFilter' ve 'login-processing-url' için. http://docs.spring.io/autorepo/docs/spring-security/3.2.0.RELEASE/reference/htmlsingle/ – SergeyB

+1

SpringConfig of Spring ile bunu denedim Güvenlik, nihayet pes etmek ve XML ftw! – Boon

2

Spring, XML tabanlı yapılandırmalardan ve Java @Configuration sınıflarına doğru kayıyor. Aşağıda, yukarıdaki postada (Spring Security Ajax login) açıklanan kurulumun @Configuration versiyonudur. Adımlar 2 & 3 aynı kalır, Adım 1'i bu kodla değiştirin. Sipariş bir kez daha önemli, daha spesifik olanların daha genel olanlardan önce yüklenmesi gerekiyor, bunu kontrol etmek için @Order(1) ve @Order(2) kullanın.

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.annotation.Order; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.config.annotation.web.builders.WebSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.web.savedrequest.HttpSessionRequestCache; 
import org.springframework.security.web.savedrequest.RequestCache; 

@Configuration 
@EnableWebSecurity 
public class WebMvcSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Bean(name = "requestCache") 
    public RequestCache getRequestCache() { 
     return new HttpSessionRequestCache(); 
    } 

    @Configuration 
    @Order(1) 
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { 

      @Autowired private RequestCache requestCache; 

      @Override 
      protected void configure(HttpSecurity http) throws Exception { 
       http 
        .regexMatcher("/rest.*") 
        .authorizeRequests() 
         .antMatchers("/rest/calendar/**") 
          .hasAuthority("ROLE_USER") 
         .antMatchers("/rest/**") 
          .permitAll() 
         .and() 
        .headers() 
         .xssProtection() 
         .and() 
        .logout() 
         .logoutUrl("/rest/security/logout-url") 
         .and() 
        .requestCache() 
         .requestCache(requestCache) 
         .and() 
        .formLogin() 
         .loginProcessingUrl("/rest/security/login-processing") 
         .loginPage("/rest/security/login-page") 
         .failureUrl("/rest/security/authentication-failure") 
         .defaultSuccessUrl("/rest/security/default-target", false) 
         .and() 
        .httpBasic(); 
      } 
    } 

    @Configuration 
    @Order(2) 
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     @Autowired private RequestCache requestCache; 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      http 
       .authorizeRequests() 
        .regexMatchers("/calendar/.*") 
         .hasAuthority("ROLE_USER") 
        .regexMatchers("/.*") 
         .permitAll() 
        .and() 
       .logout() 
        .logoutUrl("/security/j_spring_security_logout") 
        .and() 
       .requestCache() 
        .requestCache(requestCache) 
        .and() 
       .formLogin() 
        .loginProcessingUrl("/security/j_spring_security_check") 
        .loginPage("/login") 
        .failureUrl("/login?login_error=t") 
        .and() 
       .httpBasic(); 
     } 
    } 

    @Override 
    public void configure(WebSecurity web) throws Exception { 
     web 
      .ignoring() 
       .antMatchers("/resources/**") 
       .antMatchers("/sitemap.xml"); 
    } 
} 
İlgili konular