spring security ajax

转自 http://loianegroner.com/2010/02/integrating-spring-security-with-extjs-login-page/

 

This tutorial will walk through how to configure ExtJS Login form (Ajax login form) instead of default Spring Security login.jsp.

Instead of using login.jsp from spring security, why do not use an ajax login form?

And How to integrate the ExtJS Login Form with Spring Security ?

You did try to do it, the user is successfully authenticated, but the user is not redirected to the application main page. How to fix this situation? How to make it work?

It does not matter if you set the default-target-url in applicationContext-security.xml, or set a redirect URL on server side. It will not work this way.

The issue is that ExtJS make Ajax calls, and no redirect will work on server side. You have to redirect it on the client side, which is the ExtJS/javascript code.

First, you need to create the login form. You can use the javascript code provided by ExtJS and you can modify it to work with spring security.

If you take a look at the login.jsp, you will see three key points:

  1. URL / form action: j_spring_security_check
  2. Username input name: j_username
  3. Password input name: j_password

That is what you need to customize to make ExtJS Login form works! But do not be too comfortable, there are some issues you need to fix to make it work perfectly.

Take a look how login.js looks like (after customization):

01 Ext.onReady( function (){
02      Ext.QuickTips.init();
03  
04      // Create a variable to hold our EXT Form Panel.
05  
06      // Assign various config options as seen.
07      var login = new Ext.FormPanel({
08          labelWidth:80,
09          url: 'j_spring_security_check' ,
10          frame: true ,
11          title: 'Please Login' ,
12  
13          defaultType: 'textfield' ,
14          width:300,
15          height:150,
16          monitorValid: true ,
17          // Specific attributes for the text fields for username / password.
18          // The "name" attribute defines the name of variables sent to the server.
19  
20          items:[{
21              fieldLabel: 'Username' ,
22              name: 'j_username' ,
23              allowBlank: false
24          },{
25              fieldLabel: 'Password' ,
26  
27              name: 'j_password' ,
28              inputType: 'password' ,
29              allowBlank: false
30          }],
31  
32          // All the magic happens after the user clicks the button
33          buttons:[{
34  
35              text: 'Login' ,
36              formBind: true ,
37              // Function that fires when user clicks the button
38              handler: function (){
39              login.getForm().submit({
40  
41                  method: 'POST' ,
42  
43                  // Functions that fire (success or failure) when the server responds.
44                  // The server would actually respond with valid JSON,
45                  // something like: response.write "{ success: true}" or
46  
47                  // response.write "{ success: false, errors: { reason: 'Login failed. Try again.' }}"
48                  // depending on the logic contained within your server script.
49                  // If a success occurs, the user is notified with an alert messagebox,
50  
51                  // and when they click "OK", they are redirected to whatever page
52                  // you define as redirect.
53  
54                  success: function (){
55                  Ext.Msg.alert( 'Status' , 'Login Successful!' , function (btn, text){
56  
57                      if (btn == 'ok' ){
58                          window.location = 'main.action' ;
59                      }
60                  });
61  
62              },
63  
64              // Failure function, see comment above re: success and failure.
65              // You can see here, if login fails, it throws a messagebox
66              // at the user telling him / her as much.
67  
68              failure: function (form, action){
69                  if (action.failureType == 'server' ){
70                      obj = Ext.util.JSON.decode(action.response.responseText);
71  
72                      Ext.Msg.alert( 'Login Failed!' , obj.errors.reason);
73                  } else {
74                      Ext.Msg.alert( 'Warning!' , 'Authentication server is unreachable : ' + action.response.responseText);
75  
76                  }
77                  login.getForm().reset();
78              }
79  
80              });
81          }
82          }]
83      });
84  
85      login.render( 'login' );
86  
87 });

If you make these changes and try to execute the application with a basic applicationContext-security.xml file, the user will be successfully authenticated, but is not going to be redirected.

What are we missing then?

You need to customize AuthenticationProcessingFilter class for spring security to perform actions on login.

The “onSuccessfulAuthentication” and “onUnsuccessfulAuthentication” methods need to return some JSON content. If user is successfully authenticated, then redirect to main page, otherwise, the application will show an error message.

This is MyAuthenticationProcessingFilter class:

01 package com.loiane.security;
02  
03 import java.io.IOException;
04 import java.io.Writer;
05  
06 import javax.servlet.http.HttpServletRequest;
07 import javax.servlet.http.HttpServletResponse;
08 import javax.servlet.http.HttpServletResponseWrapper;
09  
10 import org.springframework.security.Authentication;
11 import org.springframework.security.AuthenticationException;
12 import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
13  
14 public class MyAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
15  
16      protected void onSuccessfulAuthentication(HttpServletRequest request,
17              HttpServletResponse response, Authentication authResult)
18      throws IOException {
19          super .onSuccessfulAuthentication(request, response, authResult);
20  
21          HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response);
22  
23          Writer out = responseWrapper.getWriter();
24  
25          String targetUrl = determineTargetUrl( request );
26          out.write( "{success:true, targetUrl : \'" + targetUrl + "\'}" );
27          out.close();
28  
29      }
30  
31      protected void onUnsuccessfulAuthentication( HttpServletRequest request,
32              HttpServletResponse response, AuthenticationException failed )
33      throws IOException {
34  
35          HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response);
36  
37          Writer out = responseWrapper.getWriter();
38  
39          out.write( "{ success: false, errors: { reason: 'Login failed. Try again.' }}" );
40          out.close();
41  
42      }
43  
44 }

And this is how applicationContext-security.xml looks like :

01 <? xml version = "1.0" encoding = "UTF-8" ?>
02  
04      xmlns:security = "http://www.springframework.org/schema/security "
05      xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance "
08  
09      < security:global-method-security />
10  
11      < security:http auto-config = "false" entry-point-ref = "authenticationProcessingFilterEntryPoint" >
12          < security:intercept-url pattern = "/index.jsp" filters = "none" />
13          < security:intercept-url pattern = "/*.action" access = "ROLE_USER" />
14      </ security:http >
15  
16      < bean id = "authenticationProcessingFilter" class = "com.loiane.security.MyAuthenticationProcessingFilter" >
17          < security:custom-filter position = "AUTHENTICATION_PROCESSING_FILTER" />
18          < property name = "defaultTargetUrl" value = "/main.html" />
19          < property name = "authenticationManager" ref = "authenticationManager" />
20      </ bean >
21  
22      < security:authentication-manager alias = "authenticationManager" />
23  
24      < bean id = "authenticationProcessingFilterEntryPoint"
25          class = "org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint" >
26          < property name = "loginFormUrl" value = "/index.jsp" />
27          < property name = "forceHttps" value = "false" />
28      </ bean >
29  
30      <!--
31      Usernames/Passwords are
32          rod/koala
33          dianne/emu
34          scott/wombat
35          peter/opal
36      These passwords are from spring security app example
37      -->
38      < security:authentication-provider >
39          < security:password-encoder hash = "md5" />
40          < security:user-service >
41              < security:user name = "rod" password = "a564de63c2d0da68cf47586ee05984d7" authorities = "ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
42              < security:user name = "dianne" password = "65d15fe9156f9c4bbffd98085992a44e" authorities = "ROLE_USER,ROLE_TELLER" />
43              < security:user name = "scott" password = "2b58af6dddbd072ed27ffc86725d7d3a" authorities = "ROLE_USER" />
44              < security:user name = "peter" password = "22b5c9accc6e1ba628cedc63a72d57f8" authorities = "ROLE_USER" />
45          </ security:user-service >
46      </ security:authentication-provider >
47 </ beans >

Now you can login using ExtJS login form.

I coded a sample application for this example. If you like it, you can download it from my GitHub: http://github.com/loiane/spring-security-extjs-login

Happy coding!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值