2013-08-13 50 views
5

Tôi có ứng dụng web SpringMVC cần xác thực dịch vụ web RESTful bằng Spring Security bằng cách gửi tên người dùng và mật khẩu. Khi người dùng được đăng nhập, cookie cần được đặt thành trình duyệt của người dùng và trong các cuộc gọi tiếp theo, phiên người dùng được xác thực bằng một dịch vụ web RESTful khác bằng cách sử dụng cookie.Spring MVC + Đăng nhập bảo mật mùa xuân bằng dịch vụ web còn lại

Tôi đã tìm kiếm ở khắp mọi nơi, nhưng tôi đã không thể tìm thấy một ví dụ tốt về cách thực hiện điều này và tất cả nỗ lực của tôi đều vô ích.

Đây là những gì tôi có trong tâm trí:

tôi có thể có hai xác thực-nhà cung cấp khai báo, kiểm tra đầu tiên cookie, và nếu nó không thành công vì lý do nào nó đi đến một giây mà kiểm tra với tên người dùng và mật khẩu (cũng sẽ thất bại nếu không có tên người dùng và mật khẩu trong yêu cầu đó).

Cả hai dịch vụ đều trả lại quyền của người dùng mỗi lần và bảo mật mùa xuân là "không quốc tịch".

Mặt khác, tôi tự đặt câu hỏi nếu cách tiếp cận này là chính xác, vì rất khó để tìm một ví dụ hoặc một người nào khác có cùng vấn đề. Cách tiếp cận này có sai không?

Lý do tôi muốn thực hiện điều này thay vì chỉ xác thực JDBC là vì toàn bộ ứng dụng web của tôi là không trạng thái và cơ sở dữ liệu luôn được truy cập thông qua các dịch vụ web RESTful bao gồm "hàng đợi kiến ​​nghị". để xác thực người dùng và xác thực quá.

Tôi đã thử gì cho đến nay? Tôi có thể dán dài springSecurity-context.xml, nhưng tôi sẽ chỉ liệt kê chúng thay vì bây giờ:

  1. Sử dụng xác thực tùy chỉnhĐặt xác thựcSuccessHandler. Rõ ràng là không hoạt động vì người dùng đã đăng nhập vào thời điểm này.
  2. Thực hiện triển khai bộ lọc tham chiếu điểm.
  3. Thực hiện bộ lọc tùy chỉnh ở vị trí BASIC_AUTH_FILTER
  4. Tạo một Nhà cung cấp xác thực tùy chỉnh (Rất nhiều khó khăn!). Tôi đang thử lại điều này trong khi tôi nhận được một số câu trả lời.
  5. Tôi bắt đầu sử dụng CAS khi tôi quyết định viết câu hỏi thay thế. Có lẽ trong tương lai tôi có thể xem xét có một máy chủ CAS trong webapp của tôi, tuy nhiên trong thời điểm này, điều này cảm thấy giống như một overkill rất lớn.

Cảm ơn bạn trước!

BTW, tôi đang sử dụng Spring Security 3.1.4 và Spring MVC 3.2.3

EDIT: Tôi đã có thể làm THANKS CHO @coder ĐÁP

Dưới đây là một số ánh sáng trên những gì tôi đã làm, tôi sẽ cố gắng ghi lại tất cả điều này và đăng nó ở đây hoặc trong một bài viết trên blog sometime sớm:

<http use-expressions="true" create-session="stateless" entry-point-ref="loginUrlAuthenticationEntryPoint" 
     authentication-manager-ref="customAuthenticationManager"> 
    <custom-filter ref="restAuthenticationFilter" position="FORM_LOGIN_FILTER" /> 
    <custom-filter ref="restPreAuthFilter" position="PRE_AUTH_FILTER" /> 
    <intercept-url pattern="/signin/**" access="permitAll" /> 
    <intercept-url pattern="/img/**" access="permitAll" /> 
    <intercept-url pattern="/css/**" access="permitAll" /> 
    <intercept-url pattern="/js/**" access="permitAll" /> 
    <intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> 

</http> 

<authentication-manager id="authManager" alias="authManager"> 
    <authentication-provider ref="preauthAuthProvider" /> 
</authentication-manager> 

<beans:bean id="restPreAuthFilter" class="com.company.CustomPreAuthenticatedFilter"> 
    <beans:property name="cookieName" value="SessionCookie" /> 
    <beans:property name="checkForPrincipalChanges" value="true" /> 
    <beans:property name="authenticationManager" ref="authManager" /> 
</beans:bean> 

<beans:bean id="preauthAuthProvider" 
    class="com.company.CustomPreAuthProvider"> 
    <beans:property name="preAuthenticatedUserDetailsService"> 
     <beans:bean id="userDetailsServiceWrapper" 
      class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> 
      <beans:property name="userDetailsService" ref="userDetailsService" /> 
     </beans:bean> 
    </beans:property> 
</beans:bean> 

<beans:bean id="userDetailsService" class="com.company.CustomUserDetailsService" /> 

<beans:bean id="loginUrlAuthenticationEntryPoint" 
    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> 
    <beans:constructor-arg value="/signin" /> 
</beans:bean> 

<beans:bean id="customAuthenticationManager" 
    class="com.company.CustomAuthenticationManager" /> 

<beans:bean id="restAuthenticationFilter" 
    class="com.company.CustomFormLoginFilter"> 
    <beans:property name="filterProcessesUrl" value="/signin/authenticate" /> 
    <beans:property name="authenticationManager" ref="customAuthenticationManager" /> 
    <beans:property name="authenticationFailureHandler"> 
     <beans:bean 
      class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> 
      <beans:property name="defaultFailureUrl" value="/login?login_error=t" /> 
     </beans:bean> 
    </beans:property> 
</beans:bean> 

Và Triển khai Tuỳ chỉnh là một cái gì đó như thế này:

// Here, the idea is to write authenticate method and return a new UsernamePasswordAuthenticationToken 
public class CustomAuthenticationManager implements AuthenticationManager { ... } 

// Write attemptAuthentication method and return UsernamePasswordAuthenticationToken 
public class CustomFormLoginFilter extends UsernamePasswordAuthenticationFilter { ... } 

// Write getPreAuthenticatedPrincipal and getPreAuthenticatedCredentials methods and return cookieName and cookieValue respectively 
public class CustomPreAuthenticatedFilter extends AbstractPreAuthenticatedProcessingFilter { ... } 

// Write authenticate method and return Authentication auth = new UsernamePasswordAuthenticationToken(name, token, grantedAuths); (or null if can't be pre-authenticated) 
public class CustomPreAuthProvider extends PreAuthenticatedAuthenticationProvider{ ... } 

// Write loadUserByUsername method and return a new UserDetails user = new User("hectorg87", "123456", Collections.singletonList(new GrantedAuthorityImpl("ROLE_USER"))); 
public class CustomUserDetailsService implements UserDetailsService { ... } 
+0

Hãy đăng câu trả lời của bạn làm câu trả lời, thay vì chỉnh sửa câu hỏi của bạn. ;) – bluish

Trả lời

3
  1. bạn có thể xác định một bộ lọc xác thực trước tùy chỉnh bằng cách mở rộng AbstractPreAuthenticatedProcessingFilter.
  2. Khi bạn triển khai phương pháp getPreAuthenticatedPrincipal(), bạn có thể kiểm tra xem cookie có tồn tại và nếu tồn tại tên cookie là tên gốc và giá trị cookie trong thông tin .
  3. Sử dụng PreAuthenticatedAuthenticationProvider và cung cấp preAuthenticatedUserDetailsService tùy chỉnh của bạn để kiểm tra xem cookie là vali, nếu cũng lấy cấp chính quyền hợp lệ của nó khác ném AuthenticationException như BadCredentialsException
  4. Đối với chứng thực người dùng bằng tên người dùng/mật khẩu, thêm một bộ lọc hình thức đăng nhập, cơ bản lọc hoặc một bộ lọc tùy chỉnh với nhà cung cấp chứng thực tùy chỉnh (hoặc tùy chỉnh userdetailsService) để xác nhận người dùng/mật khẩu

trong trường hợp cookie sẽ tồn tại, bộ lọc auth trước sẽ thiết lập người dùng xác thực trong springContext và lọc username./password của bạn sẽ không được gọi, nếu cookie sai/không hợp lệ, điểm nhập xác thực sẽ kích hoạt xác thực việc sử dụng tên người dùng/mật khẩu

Hy vọng điều này sẽ giúp

+0

Xin chào @coder, tất cả đều có ý nghĩa. Tôi sẽ thử và đăng kết quả. Cảm ơn! – hectorg87

+1

@ hector87 bạn có thể chia sẻ việc triển khai và cấu hình của mình không? cảm ơn. –

+0

Có, tôi cũng quan tâm đến việc triển khai. Bạn có thể đăng nó ở đâu đó không? Cảm ơn rất nhiều –

Các vấn đề liên quan