Announcement Announcement Module
Collapse
No announcement yet.
Spring Security and ExtJS Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Security and ExtJS

    Are there any examples of integrating ExtJS with Acegi. More specifically, I have an extJS login form that sends the j_username and j_password to the server and this is handled by Acegi's AuthenticationProcessingFilter. When returning back to the client side, however, how can I tell whether or not the client has been successfully authenticated? I have the following in my login.js:

    buttons : [{
    text : 'Login',
    formBind : true,

    handler : function() {
    login.getForm().submit({
    method : 'POST',
    waitTitle : 'Connecting',
    waitMsg : 'Sending data...',

    // Functions that fire (success or failure) when the server responds.
    // The one that executes is determined by the
    // response that comes from login.asp as seen below. The server would
    // actually respond with valid JSON,
    // something like: response.write "{ success: true}" or
    // response.write "{ success: false, errors: { reason: 'Login failed. Try again.' }}"
    // depending on the logic contained within your server script.
    // If a success occurs, the user is notified with an alert messagebox,
    // and when they click "OK", they are redirected to whatever page
    // you define as redirect.

    success : function() {
    Ext.Msg.alert('Status', 'Login Successful!', function(btn, text) {
    if (btn == 'ok') {
    var redirect = '/';
    window.location = redirect;
    }
    });
    },

    failure : function(form, action) {
    if (action.failureType == 'server') {
    obj = Ext.util.JSON.decode(action.response.responseText) ;
    Ext.Msg.alert('Login Failed!', obj.errors.reason);
    } else {
    Ext.Msg.alert('Warning!', 'Authentication server is unreachable : '
    + action.response.responseText);
    }
    login.getForm().reset();
    }
    });
    }
    }]
    });

    Currently, the user is successfully authenticated, but is not redirected. Instead, he/she just sees a progress bar saying "Sending data..." (by manually changing the page in the browser, I can tell the user is authenticated as he/she has access to the admin functions).

    I think what I need to do in login.js is get hold of the SecurityContext (yes/no?).

    I have also posted this on the ExtJS forums: http://extjs.com/forum/showthread.ph...374#post203374

    Thanks in advance.

    (I am currently using Ext 2.x and Acegi 1.0.6)
    Last edited by cornflakes; Aug 2nd, 2008, 01:26 PM. Reason: formatting

  • #2
    your question should be more detail. because Extjs only care the json result. the key point is server end how to deal with your request. Acegi only pass the authentication to back server. I am still studying the Acegi and Json_view. I maybe present the answer to after I success.

    Comment


    • #3
      Thanks, erichua.

      The server side code seems to correctly handle the request. Acegi (now Spring Security) then uses a series of filters and as you mentioned, returns an org.springframework.security.Authentication object.

      Is it possible to access this Authentication object in login.js (in my previous code snippet)?

      Thanks again.
      Last edited by cornflakes; Aug 18th, 2008, 09:53 PM.

      Comment


      • #4
        please help me

        I have 2 iframes opened. if i clicked anyware in the iframe which is actually behind, it should come to front. I tried with on click event but its not working..could you please help me regarding this??

        Even it fires documentloaded ,its not firing other events(click,focus,blur..)
        my code is..
        items:[{
        id:'newframe',
        xtype:'iframepanel',
        defaultSrc:'*.com',
        listeners:{ click: function(frame){ alert("sss"); },
        documentloaded:function (frame){alert("s");} }
        }
        ],
        wt i have to add nw

        Comment


        • #5
          Hi Cornflakes!
          The server side code seems to correctly handle the request.
          Acegi (now Spring Security) then uses a series of filters and as you mentioned,
          returns an org.springframework.security.Authentication object.

          To be specified, Acegi has own authenication.
          <bean id="authenticationProcessingFilter"
          class="org.springframework.security.ui.webapp.Auth enticationProcessingFilter">
          <property name="authenticationManager"
          ref="authenticationManager" />
          <property name="authenticationFailureUrl"
          value="/login.jsp?login_error=1" />
          <property name="defaultTargetUrl"
          value="/study/App.html" />
          <property name="filterProcessesUrl"
          value="/j_acegi_security_check" />
          </bean>
          So you should use the login.jsp instead of login.js . In the other way ,you can write your own securityContextHolder to put your authentication in.
          Welcome to discuss. I am trying to find a best way too.

          Comment


          • #6
            I ended up creating a filter that extends the AuthenticationProcessingFilter (called it AjaxAuthenticationProcessingFilter) and had to override two methods, the onSuccessfulAuthentication and onUnsuccessfulAuthentication. The class looks like:

            Code:
            public class AjaxAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
            
                /*
                 * (non-Javadoc)
                 * 
                 * @see org.springframework.security.ui.AbstractProcessingFilter#onSuccessfulAuthentication(javax.servlet.http.HttpServletRequest,
                 *      javax.servlet.http.HttpServletResponse, org.springframework.security.Authentication)
                 */
                @Override
                protected void onSuccessfulAuthentication( HttpServletRequest request, HttpServletResponse response,
                        Authentication authResult ) throws IOException {
            
                    HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper( response );
                    Writer out = responseWrapper.getWriter();
            
                    // FIXME This is too JSON-y. Use an object.
                    String targetUrl = determineTargetUrl( request );
                    out.write( "{success:true, targetUrl : \'" + targetUrl + "\'}" );
                    out.close();
                }
            
                /*
                 * (non-Javadoc)
                 * 
                 * @see org.springframework.security.ui.AbstractProcessingFilter#onUnsuccessfulAuthentication(javax.servlet.http.HttpServletRequest,
                 *      javax.servlet.http.HttpServletResponse, org.springframework.security.AuthenticationException)
                 */
                @Override
                protected void onUnsuccessfulAuthentication( HttpServletRequest request, HttpServletResponse response,
                        AuthenticationException failed ) throws IOException {
            
                    HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper( response );
                    Writer out = responseWrapper.getWriter();
            
                    // FIXME This is too JSON-y. Use an object.
                    out.write( "{ success: false, errors: { reason: 'Login failed. Try again.' }}" );
                    out.close();
            
                }
            }
            In login.js, I am doing what is outlined here:
            http://extjs.com/learn/Tutorial:Basic_Login

            This seems to work, but there are a few errors on the console I'm trying to resolve.

            Comment


            • #7
              I used almost same method as you. But there are a few of the differences.
              1. I builded a filiter that extended AuthenticationProcessingFilter
              PHP Code:
               @Override
                  
              protected void successfulAuthentication(HttpServletRequest request,
                      
              HttpServletResponse responseAuthentication authResult)
                      
              throws IOException {
                      if (
              logger.isDebugEnabled()) {
                          
              logger.debug("Authentication success: "
                              
              authResult.toString());
                      }

                      
              SecurityContextHolder.getContext().setAuthentication(authResult);

                      if (
              logger.isDebugEnabled()) {
                          
              logger.debug(
                              
              "Updated SecurityContextHolder to contain the following Authentication: '"
                              
              authResult "'");
                      }

                      
              String targetUrl determineTargetUrl(request);

                      if (
              logger.isDebugEnabled()) {
                          
              logger.debug(
                              
              "Redirecting to target URL from HTTP Session (or default): "
                              
              targetUrl);
                      }

                      
              onSuccessfulAuthentication(requestresponseauthResult);

                      
              getRememberMeServices().loginSuccess(requestresponseauthResult);

                      
              // Fire event
                      
              if (this.eventPublisher != null) {
                          
              eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
                                  
              authResultthis.getClass()));
                      }

                      if (!
              targetUrl.startsWith("http")) {
                          
              targetUrl request.getContextPath() + targetUrl;
                      }
              //send the result to another action 
                      
              sendRedirect(requestresponse,
                          
              "/login/loginSuccess.do?callback="
                          
              URLEncoder.encode(targetUrl"UTF-8"));
                  } 
              loginSuccess.do
              PHP Code:
               public void loginSuccess() throws Exception {
                      
              String callback getStrParam("callback"null);
                      
              User loginUser = (Usersession.getAttribute("loginUser");
                      
              logger.info(callback);

                      if (
              loginUser != null) {
                          
              Map<StringObjectmap = new HashMap<StringObject>();
                          
              map.put("success"true);
                          
              map.put("response"loginUser.getTruename());
                          
              map.put("callback"callback);
                          
              JsonUtils.write(mapresponse.getWriter(), nullnull);
                      } else {
                          
              response.getWriter().print("{success:false}");
                      }
                  } 
              I think this way is better because acegi has own way to deal with the authentication, it'll redirect the url to his own servelet . so I send it to my own action so that I can handle it more easier.

              Comment


              • #8
                Thanks, enrichua. So instead of sending the response directly back to the client, you are redirecting to one of your servlets first. I think that makes sense as well.

                Comment


                • #9
                  I actually made it work without having to rewrite any of my spring security modules. this is my login page:
                  Code:
                  <?xml version="1.0" encoding="ISO-8859-1" ?>
                  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                  
                  <%@ page import="org.springframework.security.context.SecurityContextHolder" %>
                  <%@ page import="org.springframework.security.context.SecurityContext" %>
                  
                  <html>
                  <head>
                  	<title>Login</title>
                  	<style type="text/css">
                  		#login-mask{
                          	position:absolute;
                  	        left:0;
                          	top:0;
                          	width:100%;
                          	height:100%;
                          	z-index:20000;
                          	background-color:white;
                      	}
                      	#login{
                  	        position:absolute;
                          	left:30%;
                          	top:35%;
                          	padding:2px;
                          	z-index:20001;
                  	        height:auto;
                      	}	
                      	#login a {
                  	        color:#225588;
                      	}
                      	#login .login-indicator{
                  	        background:white;
                          	color:#444;
                          	font:bold 13px tahoma,arial,helvetica;
                  	        padding:10px;
                          	margin:0;
                          	height:auto;
                      	}
                      	#login-msg {
                  	        font: normal 10px arial,tahoma,sans-serif;
                      	}
                  	</style>
                  	<link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/js/resources/css/ext-all.css" />
                  	<link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/js/resources/css/xtheme-gray.css" />
                  	<link rel="stylesheet" type="text/css" href="<%= request.getContextPath() %>/css/Login.css" />
                  	<script language="Javascript" src="<%= request.getContextPath() %>/js/adapter/ext/ext-base.js"></script>
                  	<script language="Javascript" src="<%= request.getContextPath() %>/js/ext-all.js"></script>
                  </head>
                  <body style="overflow: hidden">
                  <script>
                  
                  	Ext.onReady( function()
                  	{
                  		var login = new Ext.FormPanel(
                  		{
                  			labelWidth :75,
                  			url :'<%= request.getContextPath() %>/j_spring_security_check',
                  			method :'POST',
                  			id :'_loginForm',
                  			standardSubmit :true,
                  			frame :true,
                  			title :'Login',
                  			bodyStyle :'padding:5px 5px 0',
                  			iconCls :'user-suit',
                  			width :350,
                  			keys:
                  			[
                  				{
                  					key: Ext.EventObject.ENTER,
                  					fn: function()
                  			        {
                  						var sb = Ext.getCmp('my-status');
                  						sb.showBusy();
                  						document.getElementsByTagName("form")[0].action = "<%= request.getContextPath() %>/j_spring_security_check";
                  						document.getElementsByTagName("form")[0].submit();
                  			        }
                  				}
                  			],
                  			defaults :
                  		    {
                  				width :230
                  			},
                  			defaultType :'textfield',
                  			items :
                  			[
                  				{
                  					fieldLabel :'Username',
                  					name :'j_username',
                  					id :'j_username',
                  					allowBlank :false
                  				},
                  				{
                  					fieldLabel :'Password',
                  					name :'j_password',
                  					id :'j_password',
                  					allowblank :false,
                  					inputType :'password'
                  				},
                  				{
                  					xtype :'panel',
                  					buttonAlign :'right',
                  					width :340,
                  					buttons :
                  					[
                  						{
                  							text :'Reset',
                  							type :'reset',
                  							minWidth: 75,
                  							handler :function()
                  							{
                  								document.getElementsByTagName("form")[0].reset();
                  							}
                  						},
                  						{
                  							text :'Login',
                  							type :'submit',
                  							minWidth: 75,
                  							handler :function()
                  			        		{
                  								var sb = Ext.getCmp('my-status');
                  								sb.showBusy();
                  								document.getElementsByTagName("form")[0].action = "<%= request.getContextPath() %>/j_spring_security_check";
                  								document.getElementsByTagName("form")[0].submit();
                  			        		}					
                  						}
                  					]
                  				}
                  			],
                  		    bbar: new Ext.StatusBar(
                  			{
                  				id: 'my-status',
                  			        
                  			    // defaults to use when the status is cleared:
                  			    defaultText: 'Default status text',
                  			    defaultIconCls: 'default-icon',
                  			        
                  			    // values to set initially:
                  			    text: 'Ready',
                  			    iconCls: 'ready-icon'
                  		<%
                  			if (!(request.getParameter("login_error") == null))
                  			{
                  		%>
                  			    ,items:
                  				[
                  					{
                  						text: '<div style=\'color: red\'>Username/Password combination invalid.</div>'
                  					}
                  				]
                  		<%	} %>
                  		    })
                  		});
                  		login.render(document.getElementById('_login'));
                  	});
                  
                  </script>
                  <div id="login-mask" style=""></div>
                  <div id="login">
                      <div id="_login" class="login-indicator"></div>
                  </div>
                  </body>
                  </html>
                  Now I'm working on pulling the Authentication request failed: org.springframework.security.BadCredentialsExcepti on message and using that instead of the hardcoded 'User/Pass combo failure' meessage.
                  Last edited by greco; Aug 27th, 2008, 10:26 AM.

                  Comment


                  • #10
                    Thanks, greco. I'm trying to get this to work with my app as I would rather avoid using a custom authentication filter. For some reason, this form doesn't seem to hit my app. I changed j_spring_security_check to j_security_check as that is what I have mapped in my web.xml and applicationContext-security.xml.

                    In my authenticationProcessingFilter, I have:
                    Code:
                    <bean id="authenticationProcessingFilter"
                    		class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
                    		<property name="authenticationManager">
                    			<ref local="authenticationManager" />
                    		</property>
                    		<property name="authenticationFailureUrl">
                    			<value>/login.jsp?error=true</value>
                    		</property>
                    		<property name="defaultTargetUrl">
                    			<value>/Foo</value>
                    		</property>
                    		<property name="filterProcessesUrl">
                    			<value>/j_security_check</value>
                    		</property>
                    		<property name="rememberMeServices" ref="rememberMeServices" />
                    	</bean>
                    Any ideas?

                    Thanks again.
                    Last edited by cornflakes; Aug 28th, 2008, 07:13 AM.

                    Comment


                    • #11
                      Read your PM, are you sure the ext-base.js and ext-all.js are being loaded? I noticed the only js you were referencing was a DwrProxy one. Does this load the ext required js libraries?

                      Comment


                      • #12
                        They show up in firebug, but the following jawr link shows that some extra configuration is needed to use jawr with html:

                        https://jawr.dev.java.net/docs/plain_html.html

                        This could be the issue with using that form as is (because of the html elements).

                        Comment


                        • #13
                          Hi greco!
                          Do you use the Jsp? I choose the HTML as the page. I think it's a better way to use Jsp. I'll try it.

                          thanks

                          Comment


                          • #14
                            I'm trying to use that jsp provided by greco but I'm running into issues that I think have to do with my use of jawr (I'm still looking at it).

                            Comment


                            • #15
                              I ended up removing the scriplet portions in the jsp and moved everything to javascript because we are using jawr. That is, I commented out the error message scriplet (I still have to show that). I'm also using j_security_check as opposed to the default j_spring_security_check. You can use anything, just make sure you set this in your applicationContext-security.xml and web.xml files.

                              This looks like:

                              Code:
                              Ext.namespace('Foo');
                              Ext.BLANK_IMAGE_URL = '/Foo/images/default/s.gif';
                              
                              Ext.onReady(function() {
                              	Ext.QuickTips.init();
                              
                              	var login = new Ext.FormPanel({
                              		labelWidth : 75,
                              		url : 'j_security_check',
                              		method : 'POST',
                              		id : '_loginForm',
                              		standardSubmit : true,
                              		frame : true,
                              		title : 'Login',
                              		bodyStyle : 'padding:5px 5px 0',
                              		iconCls : 'user-suit',
                              		width : 350,
                              		keys : [{
                              			key : Ext.EventObject.ENTER,
                              			fn : function() {
                              				var sb = Ext.getCmp('my-status');
                              				sb.showBusy();
                              				document.getElementsByTagName("form")[0].action = 'j_security_check';;
                              				document.getElementsByTagName("form")[0].submit();
                              			}
                              		}],
                              		defaults : {
                              			width : 230
                              		},
                              		defaultType : 'textfield',
                              		items : [{
                              			fieldLabel : 'Username',
                              			name : 'j_username',
                              			id : 'j_username',
                              			allowBlank : false
                              		}, {
                              			fieldLabel : 'Password',
                              			name : 'j_password',
                              			id : 'j_password',
                              			allowblank : false,
                              			inputType : 'password'
                              		}, {
                              			boxLabel : 'Remember Me',
                              			name : 'rememberMe',
                              			inputType : 'checkbox',
                              			labelSeparator : ''
                              		}, {
                              			xtype : 'panel',
                              			buttonAlign : 'right',
                              			width : 340,
                              			buttons : [{
                              				text : 'Reset',
                              				type : 'reset',
                              				minWidth : 75,
                              				handler : function() {
                              					document.getElementsByTagName("form")[0].reset();
                              				}
                              			}, {
                              				text : 'Login',
                              				type : 'submit',
                              				minWidth : 75,
                              				handler : function() {
                              					var sb = Ext.getCmp('my-status');
                              					sb.showBusy();
                              					document.getElementsByTagName("form")[0].action = 'j_security_check';;
                              					document.getElementsByTagName("form")[0].submit();
                              				}
                              			}]
                              		}],
                              		bbar : new Ext.StatusBar({
                              			id : 'my-status',
                              			text : 'Ready',
                              			iconCls : 'default-icon',
                              			busyText : 'Validating...'
                              		// <%
                              		// if (!(request.getParameter("login_error") == null))
                              		// {
                              		// String errorMsg =
                              		// request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION").toString();
                              		// errorMsg = errorMsg.substring(errorMsg.indexOf(':') + 1, errorMsg.length());
                              		// %>
                              		// ,items:
                              		// [
                              		// '<div style=\'color: red; vertical-align: top; padding-right:
                              		// 5px;\'><%=errorMsg%><br/></div>'
                              		// ]
                              		// <% } %>
                              
                              		})
                              	});
                              	login.render(document.getElementById('_login'));
                              });

                              Comment

                              Working...
                              X