Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    #16
    I moved the authorization to mysql/sqlserver successfully (incl. salted password)!
    used: spring security 3.0.3

    NOTE1: add column salt (VARCHAR(25)) to your (spring security, standard db schema) users table.

    NOTE2: replace spring.jar from smartgwt with spring 3.0.3 release and so on.
    Code:
     
    org.springframework.aop-3.0.3.RELEASE.jar
    org.springframework.asm-3.0.3.RELEASE.jar
    org.springframework.beans-3.0.3.RELEASE.jar
    org.springframework.context-3.0.3.RELEASE.jar
    org.springframework.core-3.0.3.RELEASE.jar
    org.springframework.expression-3.0.3.RELEASE.jar
    org.springframework.jdbc-3.0.3.RELEASE.jar
    org.springframework.orm-3.0.3.RELEASE.jar
    org.springframework.transaction-3.0.3.RELEASE.jar
    org.springframework.web-3.0.3.RELEASE.jar
    org.springframework.web.servlet-3.0.3.RELEASE.jar
    spring-security-config-3.0.3.RELEASE.jar
    spring-security-core-3.0.3.RELEASE.jar
    spring-security-web-3.0.3.RELEASE.jar
    add
    Code:
    	<context:annotation-config />
    	<context:component-scan base-package="com.package..."/>
    to ...-servlet.xml

    add
    Code:
    <beans:bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<beans:property name="location" value="/WEB-INF/classes/server.properties"/>
    	</beans:bean>
    
    	<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">	
    		<beans:property name="driverClassName" value="${sql.mainDataBase.driver}"/>
    		<beans:property name="url" value="${sql.mainDataBase.driver.url}"/>
    		<beans:property name="username" value="${sql.mainDataBase.driver.user}"/>
    		<beans:property name="password" value="${sql.mainDataBase.driver.password}"/>
    	</beans:bean>
    
    	<beans:bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource"> 
    		<beans:property name="userPropertyToUse" value="salt"/>
    	</beans:bean>
    	
    	<beans:bean class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" id="passwordEncoder"/>
    	<context:annotation-config />
    	<context:component-scan base-package="com.package..."/>
    to applicationContext.xml

    add
    Code:
    <beans:bean id="jdbcUserService" class="com.pay.server.authentication.PayJdbcDaoImpl"> 
    		<beans:property name="dataSource" ref="dataSource"/> 
    		<beans:property name="authenticationManager" ref="authenticationManager"/>
    		<beans:property name="enableGroups" value="true"/>
    		<beans:property name="enableAuthorities" value="false"/>
    		<beans:property name="usersByUsernameQuery">
    			<beans:value>select username, password, enabled, salt from users where username = ?</beans:value>
    		</beans:property>
    		
    	</beans:bean>
    	<security:authentication-manager alias="authenticationManager">
    		<security:authentication-provider user-service-ref="jdbcUserService">
    			<security:password-encoder ref="passwordEncoder">
    				<security:salt-source ref="saltSource"/>
    			</security:password-encoder>
    		</security:authentication-provider>
    	</security:authentication-manager>
        <beans:bean id="formLoginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
            <beans:property name="sessionAuthenticationStrategy" ref="sessionAuthenticationStrategy"/>
            <beans:property name="authenticationManager" ref="authenticationManager"/>
            <beans:property name="authenticationSuccessHandler">
                <beans:bean class="com.pay.server.authentication.PayAuthenticationSuccessHandler"/>
            </beans:property>
            <beans:property name="authenticationFailureHandler">
                <beans:bean class="com.pay.server.authentication.PayAuthenticationFailureHandler"/>
            </beans:property>
        </beans:bean>
        <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
        <beans:bean id="loggerListener" class="org.springframework.security.access.event.LoggerListener" />
    to applicationContext-security.xml

    xmlHeader for this files:
    Code:
    <?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"
        xmlns:jdbc="http://www.springframework.org/schema/jdbc"
        xmlns:security="http://www.springframework.org/schema/security"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        					http://www.springframework.org/schema/jdbc
    						http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
                            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    DatabasePasswordSecurerBean.java
    Code:
    /**
     * Secures the database by updating user passwords.
     * 
     */
    public class DatabasePasswordSecurerBean extends JdbcDaoSupport {
    	@Autowired
    	private PasswordEncoder passwordEncoder;
    
    	@Autowired
    	private SaltSource saltSource;
    	@Autowired
    	private UserDetailsService userDetailsService;
    	
    	public void secureDatabase() {
    		getJdbcTemplate().query("select username, password from users", new RowCallbackHandler(){
    			@Override
    			public void processRow(ResultSet rs) throws SQLException {
    				String username = rs.getString(1);
    				String password = rs.getString(2);
    
    				UserDetails user = userDetailsService.loadUserByUsername(username);
    				String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));
    
    				getJdbcTemplate().update("update users set password = ? where username = ?", 
    						encodedPassword, 
    						username);
    				logger.debug("Updating password for username: "+username+" to: "+encodedPassword);
    			}			
    		});
    	}
    IChangePassword.java
    Code:
     public interface IChangePassword extends UserDetailsService {
    	void changePassword(String username, String password);
    }
    IPTokenBasedRememberMeServices.java
    Code:
     public class IPTokenBasedRememberMeServices extends
    		TokenBasedRememberMeServices {
    
        private static final ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<HttpServletRequest>();
    
        public HttpServletRequest getContext() {
            return requestHolder.get();
        }
    
        public void setContext(HttpServletRequest context) {
            requestHolder.set(context);
        }
        
        protected String getUserIPAddress(HttpServletRequest request) {
    		return request.getRemoteAddr();
    	}
    	
    	// lifecycle methods
    	
    	@Override
    	public void onLoginSuccess(HttpServletRequest request,
    			HttpServletResponse response,
    			Authentication successfulAuthentication) {
    		try
    		{
    			setContext(request);
    			super.onLoginSuccess(request, response, successfulAuthentication);
    		}
    		finally
    		{
    			setContext(null);
    		}
    	}
    
    
    	@Override
    	protected UserDetails processAutoLoginCookie(String[] cookieTokens,
    			HttpServletRequest request, HttpServletResponse response) {
    		try
    		{
    			setContext(request);
    			// take off the last token
    			String ipAddressToken = cookieTokens[cookieTokens.length-1];
    			if(!getUserIPAddress(request).equals(ipAddressToken))
    			{
    				throw new InvalidCookieException("Cookie IP Address did not contain a matching IP (contained '" + ipAddressToken + "')");
    			}
    			
    			return super.processAutoLoginCookie(Arrays.copyOf(cookieTokens, cookieTokens.length-1), request, response);
    		}
    		finally
    		{
    			setContext(null);
    		}
    	}	
    	
    	// the worker methods
    	
    	@Override
    	protected String makeTokenSignature(long tokenExpiryTime, String username,
    			String password) {
            return DigestUtils.md5DigestAsHex((username + ":" + tokenExpiryTime + ":" + password + ":" + getKey() + ":" + getUserIPAddress(getContext())).getBytes());
    	}
    
    	@Override
    	protected void setCookie(String[] tokens, int maxAge,
    			HttpServletRequest request, HttpServletResponse response) {
    		// append the IP adddress to the cookie
    		String[] tokensWithIPAddress = Arrays.copyOf(tokens, tokens.length+1);
    		tokensWithIPAddress[tokensWithIPAddress.length-1] = getUserIPAddress(request);
    		super.setCookie(tokensWithIPAddress, maxAge, request, response);
    	}
    PayDBPasswordSecurerBean.java
    Code:
     public class PayDBPasswordSecurerBean extends JdbcDaoSupport { 
    	
    	@Autowired 
    	private PasswordEncoder passwordEncoder;
    	
    	@Autowired 
    	private SaltSource saltSource; 
    	
    	@Autowired 
    	private UserDetailsService userDetailsService;
    	
    	public void secureDatabase() { 
    		getJdbcTemplate().query("select username, password from users", new RowCallbackHandler(){
    
    			@Override 
    			public void processRow(ResultSet rs) throws SQLException {
    
    				String username = rs.getString(1); 
    				String password = rs.getString(2); 
    				
    				UserDetails user = userDetailsService.loadUserByUsername(username); 
    				String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));
    				
    				getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); 
    				logger.debug("Updating password for username:" + username+" to: "+encodedPassword);
    				
    			}
    		});
    	}
    PayJdbcDaoImpl.java
    Code:
     public class PayJdbcDaoImpl extends JdbcUserDetailsManager implements IChangePassword {
    
    	@Autowired
    	private PasswordEncoder passwordEncoder;
    	@Autowired
    	private SaltSource saltSource;
    
    	public void changePassword(String username, String password) {
    
    		UserDetails user = loadUserByUsername(username);
    		String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));
    		getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", encodedPassword, username);
    	}
    
    	@Override
    	protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery, List<GrantedAuthority> combinedAuthorities) {
            String returnUsername = userFromUserQuery.getUsername();
    
            if (!isUsernameBasedPrimaryKey()) {
                returnUsername = username;
            }
    
            return new PaySaltedUser(returnUsername, userFromUserQuery.getPassword(), userFromUserQuery.isEnabled(),
                    true, true, true, combinedAuthorities, ((PaySaltedUser) userFromUserQuery).getSalt());
    	}
    
    	@Override
    	protected List<UserDetails> loadUsersByUsername(String username) {
            return getJdbcTemplate().query(getUsersByUsernameQuery(), new String[] {username}, new RowMapper<UserDetails>() {
                public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
                    String username = rs.getString(1);
                    String password = rs.getString(2);
                    boolean enabled = rs.getBoolean(3);
                    String salt = rs.getString(4);
                    return new PaySaltedUser(username, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES, salt);
                }
            });
    	}
    PaySaltedUser.java
    Code:
     public class PaySaltedUser extends User {
    
    	private static final long serialVersionUID = 896890224687744910L;
    	
    	private String salt;
    
    	public PaySaltedUser(String username, String password, boolean enabled,
    			boolean accountNonExpired, boolean credentialsNonExpired,
    			boolean accountNonLocked, List<GrantedAuthority> authorities, String salt) {
    		super(username, password, enabled, accountNonExpired, credentialsNonExpired,
    				accountNonLocked, authorities);
    		this.salt = salt;
    	}
    
    	public String getSalt() {
    		return salt;
    	}
    
    	public void setSalt(String salt) {
    		this.salt = salt;
    	}
    b.t.w. DriverManagerDataSource is not perferct, but it works :-).
    next step: migration to JNDI Datasource with tx handler.

    I hope I was able to help some people.

    Cheers,
    Timo

    Comment


      #17
      Hello Timo,

      Thanks for posting all this! But since i'm a Spring (Security) newbie, some questions:

      1) Did you use the login-form of the example that was first posted here?
      1b) If yes, did you modify it with remember me stuff and maybe a forgot-password part/register new user part?
      2) How did you build a system where new users can be added, do you have some example code? Maybe a listgrid showing all the users with a 'new' button?

      Hopefully you (or someone else) could provide some hints on this. Thanks.

      Comment


        #18
        Hi Kah0ona,

        1) I have only extended the implementation of hanishi (first post). (with sgwt login window)
        1b) The "Remember me" functionality, I will implement in the coming weeks.
        2) "add new user" and "change password" are functions in the application itself.
        i call spring bean PayJdbcDaoImpl (DMI) with Method changePassword and createUserDetails.

        NOTE: The subject is so important and complex, I can recommend the book http://www.springsecuritybook.com/.
        alternative spring forum

        Regard,
        Timo

        Comment


          #19
          Alright, thanks alot!

          So in order to use changePassword and createUserDetails (this one creates a new user?), I need to call these methods using DMI, right? I will start this tonight. Thanks. I will probably be stuck on some stuff, but then i'll add a reply here :-)

          Comment


            #20
            createUserDetails is for "add new User"
            changePassword is for "change User Password"

            >>> PLEASE READ BEFORE A BOOK ABOUT SPRING SECURITY <<<

            Security is to important.

            Comment


              #21
              Thanks. Since I like reading books, I actually followed your suggestion and ordered it. will take few weeks for it arrives, but got plenty of work to do until then, so no problem.

              Comment


                #22
                Originally posted by Kah0ona
                will take few weeks for it arrives
                where do you live? Delivery in two days with Amazon. :-)

                Comment


                  #23
                  Netherlands. Ordered via Amazon.COM. Should've used .co.uk obviously, but I thought that they'd share orders, but they don't, so i expect it to take longer.
                  We'll see.
                  Last edited by Kah0ona; 21 Aug 2010, 02:11.

                  Comment


                    #24
                    What has been your solution for obtaining the information of the currently logged in user? And how did you handle logout?
                    Last edited by Kah0ona; 21 Aug 2010, 11:24.

                    Comment


                      #25
                      Nevermind about my last posts rambling. I did some RTFM and managed a lot of stuff.

                      One thing though. There were rumours that sending the marker to the client in IE is not being executed. Is this still the case in IE7 or 8 or 9?

                      Is there a solution that works around this, without telling ppl to change the security settings?

                      Regards,

                      Marten

                      Comment


                        #26
                        Getting there. I'm loving this approach. Anyone tried in IE7+ yet?
                        Last edited by Kah0ona; 4 Oct 2010, 07:12.

                        Comment


                          #27
                          I am trying to implement the samples for SpringSecurity 3.0 posted on the first page of this thread and while I am not getting errors in onModuleLoad, I don't get the login screen showing.

                          I did a few GWT.log in RPCManager.setLoginRequiredCallback, but the LoginRequired Callback is not executing. Any ideas as to why?

                          I have authentication.defaultRequired: true in server.properties

                          MainForm.java which is my entry point:

                          Code:
                             private static final String CREDENTIALS_URL="/showcase/j_spring_security_check";
                              private LoginWindow loginWindow;
                              private LoginForm loginForm;
                              //private ApplicationPanel panel;
                          
                              public void onModuleLoad() 
                              {
                                  /****/
                                  RPCManager.setLoginRequiredCallback(new LoginRequiredCallback()
                                  {
                                      
                                      @Override
                                      public void loginRequired(int i, RPCRequest rpcRequest, RPCResponse rpcResponse) 
                                      {
                                      
                                          GWT.log("Is In");
                                          
                                          loginWindow=new LoginWindow();
                                          /**
                                            if(loginWindow==null)
                                           
                                              loginWindow=new LoginWindow();
                                          if(!(loginWindow.isVisible() && loginWindow.isDrawn())){
                                              loginForm.clearValues();
                                              loginForm.focusInItem("username");
                                          }
                                          **/
                                          GWT.log("In after show");
                                          loginWindow.show();
                                          loginWindow.bringToFront();
                                      }
                                  });
                                  /** **/
                                  RootPanel.get("loadingWrapper").setVisible(false);
                                 // IButton buttonItem = new IButton("Swap titles");
                                 GWT.log("Is Logged In");
                                  // panel=new ApplicationPanel();
                                 // panel.draw();
                              }
                          Here are is my full source:

                          Code:
                           public class LoginWindow extends Window {
                              	 
                                  public LoginWindow(){
                                      loginForm=new LoginForm(CREDENTIALS_URL);
                                      setShowModalMask(true);
                                      centerInPage();
                                      setShowCloseButton(false);
                                      setShowMinimizeButton(false);
                                      setIsModal(true);
                                      setAutoSize(true);
                                      addItem(loginForm);
                                  }
                              }
                          
                              private class LoginForm extends DynamicForm 
                              {
                                  private String credentialsURL;
                          
                                  public LoginForm(String credentialsURL)
                                  {
                                      this.credentialsURL=credentialsURL;
                                      BlurbItem blurbItem=new BlurbItem("loginFailure");
                                      blurbItem.setVisible(false);
                                      blurbItem.setColSpan(2);
                                      blurbItem.setDefaultValue("Invalid username or password");
                                      blurbItem.setCellStyle("formCellError");
                                      
                                      TextItem textItem=new TextItem();
                                      textItem.setTitle("Username: ");
                                      textItem.setTitleOrientation(TitleOrientation.LEFT);
                                      
                                      /**
                                      textItem.addKeyPressHandler(new KeyPressHandler()
                                      {
                                          @Override
                                          public void onKeyPress(KeyPressEvent keyPressEvent) {
                                              if(keyPressEvent.getKeyName().equals("Enter")){
                                                  focusInItem("password");
                                              }
                                          }
                                      });
                                      **/
                              
                                      PasswordItem passwordItem=new PasswordItem();
                                      passwordItem.setTitle("password");
                                      passwordItem.setTitleOrientation(TitleOrientation.LEFT);
                                      
                                      /**
                                      passwordItem.addKeyPressHandler(new KeyPressHandler(){
                                          @Override
                                          public void onKeyPress(KeyPressEvent keyPressEvent) {
                                              if(keyPressEvent.getKeyName().equals("Enter")){
                                                  doLogin();
                                              }
                                          }
                                      });
                                     
                                      ButtonItem buttonItem=new ButtonItem("Login");
                                      buttonItem.addClickHandler(new ClickHandler()
                                      {
                                          @Override
                                          public void onClick(ClickEvent clickEvent) 
                                          {
                                              doLogin();
                                          }
                                      });
                                      **/
                                     
                          
                                      
                                       IButton buttonItem = new IButton("Login");  
                                       buttonItem.setLeft(300);  
                                       buttonItem.addClickHandler(new ClickHandler() 
                                       {
                          				@Override
                          				public void onClick(ClickEvent event) 
                          				{
                          					doLogin();	
                          				}  				
                                       }); 
                                     
                                       /**  IButton buttonItem = new IButton("Swap titles"); 
                                     // IButtonItem buttonItem=new ButtonItem("Login");
                                      buttonItem.addClickHandler( new ClickHandler() 
                                      {  
                                      			public void onClick(ClickEvent event) 
                                      			{
                                      				doLogin();
                                      			}	
                                      }				
                                      });
                                      **/
                                       this.setFields(new FormItem[] {textItem,passwordItem});
                                       this.addChild(buttonItem);
                                      //setFields(textItem,passwordItem,buttonItem);
                                  }
                          
                                  public void doLogin(){
                                      RPCRequest request=new RPCRequest();
                                      request.setContainsCredentials(true);
                                      request.setActionURL(credentialsURL);
                                      request.setUseSimpleHttp(true);
                                      request.setShowPrompt(false);
                                      Map<String,String> params=new HashMap<String,String>();
                                      params.put("j_username",getValueAsString("username"));
                                      params.put("j_password",getValueAsString("password"));
                                      request.setParams(params);
                                      
                                      RPCManager.sendRequest(request,new RPCCallback(){
                                          @Override
                                          public void execute(RPCResponse response, Object rawData, RPCRequest request) {
                                              clearValues();
                                              if(response.getStatus()==RPCResponse.STATUS_SUCCESS)
                                              {
                                              	GWT.log("login success");
                                                  hideItem("loginFailure");
                                                  RPCManager.resendTransaction();
                                                  loginWindow.hide();
                                              }
                                              else if(response.getStatus()==RPCResponse.STATUS_LOGIN_INCORRECT)
                                              {
                                                  showItem("loginFailure");
                                                  GWT.log("login failure");
                                              }
                                              else if(response.getStatus()==RPCResponse.STATUS_MAX_LOGIN_ATTEMPTS_EXCEEDED)
                                              {
                                                  SC.warn("Max login attempts exceeded.");
                                                  GWT.log("max login attempts");
                                              }
                                              GWT.log("in sendRequest");
                                              //TODO focusInItem("username");
                                          }
                                      });
                                  }
                              }
                          BiztrackMarkerResponseHandler:

                          Code:
                           
                          package com.smartgwt.sample.showcase.server.authentication;
                          
                          import java.io.IOException;
                          import java.io.PrintWriter;
                          
                          import javax.servlet.ServletException;
                          import javax.servlet.http.HttpServletRequest;
                          import javax.servlet.http.HttpServletResponse;
                          
                          import org.springframework.security.core.Authentication;
                          import org.springframework.security.core.AuthenticationException;
                          
                          public abstract class BiztrackMarkerResponseHandler 
                          {
                              protected static final String LOGIN_REQUIRED_MARKER="<SCRIPT>//'\"]]>>isc_loginRequired\n" +
                                      "//\n" +
                                      "// Embed this whole script block VERBATIM into your login page to enable\n" +
                                      "// SmartClient RPC relogin.\n" +
                                      "\n" +
                                      "while (!window.isc && document.domain.indexOf(\".\") != -1) {\n" +
                                      "    try {\n" +
                                      "\t\n" +
                                      "        if (parent.isc == null) {\n" +
                                      "            document.domain = document.domain.replace(/.*?\\./, '');\n" +
                                      "            continue;\n" +
                                      "        } \n" +
                                      "        break;\n" +
                                      "    } catch (e) {\n" +
                                      "        document.domain = document.domain.replace(/.*?\\./, '');\n" +
                                      "    }\n" +
                                      "}\n" +
                                      "\n" +
                                      "var isc = top.isc ? top.isc : window.opener ? window.opener.isc : null;\n" +
                                      "if (isc) isc.RPCManager.delayCall(\"handleLoginRequired\", [window]);\n" +
                                      "</SCRIPT>";
                              
                              protected final String SUCCESS_MARKER="<SCRIPT>//'\"]]>>isc_loginSuccess\n" +
                                      "//\n" +
                                      "// When doing relogin with a webserver-based authenticator, protect this page with it and\n" +
                                      "// target your login attempts at this page such that when the login succeeds, this page is\n" +
                                      "// returned.\n" +
                                      "//\n" +
                                      "// If you are integrating with a web service that returns a fault, paste this entire script\n" +
                                      "// block VERBATIM into the fault text.\n" +
                                      "\n" +
                                      "while (!window.isc && document.domain.indexOf(\".\") != -1) {\n" +
                                      "    try {\n" +
                                      "        if (parent.isc == null) {\n" +
                                      "            document.domain = document.domain.replace(/.*?\\./, '');\n" +
                                      "            continue;\n" +
                                      "        } \n" +
                                      "        break;\n" +
                                      "    } catch (e) {\n" +
                                      "        document.domain = document.domain.replace(/.*?\\./, '');\n" +
                                      "    }\n" +
                                      "}\n" +
                                      "\n" +
                                      "var isc = top.isc ? top.isc : window.opener ? window.opener.isc : null;\n" +
                                      "if (isc) isc.RPCManager.delayCall(\"handleLoginSuccess\", [window]);\n" +
                                      "</SCRIPT>";
                              
                              private String markerSnippet;
                          
                              protected void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication)
                                      throws IOException, ServletException {
                                  PrintWriter writer=httpServletResponse.getWriter();
                                  writer.print(markerSnippet);
                                  httpServletResponse.flushBuffer();
                              }
                          
                              protected void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e)
                                      throws IOException, ServletException {
                                  PrintWriter writer=httpServletResponse.getWriter();
                                  writer.print(markerSnippet);
                                  httpServletResponse.flushBuffer();
                              }
                          
                              protected void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
                                      throws IOException{
                                  PrintWriter writer=httpServletResponse.getWriter();
                                  writer.print(markerSnippet);
                                  httpServletResponse.flushBuffer();
                              }
                          
                              public String getMarkerSnippet() {
                                  return markerSnippet;
                              }
                          
                              public void setMarkerSnippet(String markerSnippet) {
                                  this.markerSnippet = markerSnippet;
                              }
                          }
                          BiztrackInvalidSessionHandler:

                          Code:
                            
                          package com.smartgwt.sample.showcase.server.authentication;
                          
                          import java.io.IOException;
                          
                          import javax.servlet.ServletException;
                          import javax.servlet.http.HttpServletRequest;
                          import javax.servlet.http.HttpServletResponse;
                          
                          import org.apache.commons.logging.Log;
                          import org.apache.commons.logging.LogFactory;
                          
                          public class BiztrackInvalidSessionHandler extends BiztrackMarkerResponseHandler
                          implements InvalidSessionHandler {
                          protected final Log logger = LogFactory.getLog(getClass());
                          
                          public BiztrackInvalidSessionHandler(){
                          setMarkerSnippet(LOGIN_REQUIRED_MARKER);
                          }
                          
                          @Override
                          public void sessionInvalidated(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
                          if(logger.isDebugEnabled())
                              logger.debug("responded with LOGIN_REQUIRED_MARKER");
                          handle(request,response);
                          }
                          }
                          BiztrackConcurrentSessionFilter:

                          Code:
                          package com.smartgwt.sample.showcase.server.authentication;
                          
                          import java.io.IOException;
                          
                          import javax.servlet.FilterChain;
                          import javax.servlet.ServletException;
                          import javax.servlet.ServletRequest;
                          import javax.servlet.ServletResponse;
                          import javax.servlet.http.HttpServletRequest;
                          import javax.servlet.http.HttpServletResponse;
                          import javax.servlet.http.HttpSession;
                          
                          import org.springframework.security.core.Authentication;
                          import org.springframework.security.core.context.SecurityContextHolder;
                          import org.springframework.security.core.session.SessionInformation;
                          import org.springframework.security.core.session.SessionRegistry;
                          import org.springframework.security.web.authentication.logout.LogoutHandler;
                          import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
                          import org.springframework.util.Assert;
                          import org.springframework.web.filter.GenericFilterBean;
                          
                          public class BiztrackConcurrentSessionFilter extends GenericFilterBean {
                              private SessionRegistry sessionRegistry;
                              private InvalidSessionHandler invalidSessionHandler;
                          
                              private LogoutHandler[] handlers = new LogoutHandler[] {new SecurityContextLogoutHandler()};
                          
                              public void afterPropertiesSet(){
                                  Assert.notNull(sessionRegistry,"SessionRegistry required");
                                  Assert.notNull(invalidSessionHandler,"InvalidSessionHandler required");
                              }
                          
                              public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {
                                  HttpServletRequest request=(HttpServletRequest)req;
                                  HttpServletResponse response=(HttpServletResponse)res;
                                  HttpSession session=request.getSession(false);
                                  if(session!=null){
                                      SessionInformation info=sessionRegistry.getSessionInformation(session.getId());
                                      if(info!=null){
                                          if(info.isExpired()){
                                              doLogout(request,response);
                                              if(invalidSessionHandler!=null)
                                                  invalidSessionHandler.sessionInvalidated(request,response);
                                              else{
                                                  response.getWriter().print("This session has been expired (possibly due to multiple concurrent " +
                           	                               "logins being attempted as the same user).");
                                                  response.flushBuffer();
                                              }
                                              return;
                                          }else{
                                              info.refreshLastRequest();
                                          }
                                      }
                                  }
                                  chain.doFilter(request,response);
                              }
                          
                              private void doLogout(HttpServletRequest request, HttpServletResponse response) {
                                  Authentication auth = SecurityContextHolder.getContext().getAuthentication();
                                  for(int i=0; i<handlers.length; i++)
                                      handlers[i].logout(request, response, auth);
                              }
                          
                              public void setInvalidSessionHandler(InvalidSessionHandler invalidSessionHandler) {
                                  this.invalidSessionHandler = invalidSessionHandler;
                              }
                              
                              public void setLogoutHandlers(LogoutHandler[] handlers) {
                                  Assert.notNull(handlers);
                                  this.handlers = handlers;
                              }
                          
                              public void setSessionRegistry(SessionRegistry sessionRegistry) {
                                  this.sessionRegistry = sessionRegistry;
                              }
                          }
                          BiztrackAuthenticationSuccessHandler:

                          Code:
                           
                          package com.smartgwt.sample.showcase.server.authentication;
                          
                          import java.io.IOException;
                          
                          import javax.servlet.ServletException;
                          import javax.servlet.http.HttpServletRequest;
                          import javax.servlet.http.HttpServletResponse;
                          
                          import org.apache.commons.logging.Log;
                          import org.apache.commons.logging.LogFactory;
                          import org.springframework.security.core.Authentication;
                          import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
                          
                          public class BiztrackAuthenticationSuccessHandler extends BiztrackMarkerResponseHandler
                          implements AuthenticationSuccessHandler {
                          protected final Log logger = LogFactory.getLog(getClass());
                          public BiztrackAuthenticationSuccessHandler(){
                          setMarkerSnippet(SUCCESS_MARKER);
                          }
                          
                          @Override
                          public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                          if(logger.isDebugEnabled())
                              logger.debug("responded with SUCCESS_MARKER");
                          handle(httpServletRequest,httpServletResponse,authentication);
                          }
                          }
                          BiztrackAuthenticationFailureHandler:

                          Code:
                           
                          package com.smartgwt.sample.showcase.server.authentication;
                          
                          import java.io.IOException;
                          
                          import javax.servlet.ServletException;
                          import javax.servlet.http.HttpServletRequest;
                          import javax.servlet.http.HttpServletResponse;
                          
                          import org.apache.commons.logging.Log;
                          import org.apache.commons.logging.LogFactory;
                          import org.springframework.security.core.AuthenticationException;
                          import org.springframework.security.web.authentication.AuthenticationFailureHandler;
                          
                          public class BiztrackAuthenticationFailureHandler extends BiztrackMarkerResponseHandler
                          implements AuthenticationFailureHandler {
                          protected final Log logger = LogFactory.getLog(getClass());
                          
                          public BiztrackAuthenticationFailureHandler(){
                          setMarkerSnippet(LOGIN_REQUIRED_MARKER);
                          }
                          
                          @Override
                          public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                          if(logger.isDebugEnabled())
                              logger.debug("responded with LOGIN_REQUIRED_MARKER");
                          handle(httpServletRequest,httpServletResponse,e);
                          }
                          }
                          BiztrackAuthenticationEntryPoint:

                          Code:
                           
                          package com.smartgwt.sample.showcase.server.authentication;
                          
                          import java.io.IOException;
                          
                          import javax.servlet.ServletException;
                          import javax.servlet.http.HttpServletRequest;
                          import javax.servlet.http.HttpServletResponse;
                          
                          import org.springframework.security.core.AuthenticationException;
                          import org.springframework.security.web.AuthenticationEntryPoint;
                          
                          public class BiztrackAuthenticationEntryPoint extends BiztrackMarkerResponseHandler implements AuthenticationEntryPoint {
                          
                          	public BiztrackAuthenticationEntryPoint()
                          	{
                          		setMarkerSnippet(LOGIN_REQUIRED_MARKER);
                          	}
                          	
                          	@Override
                          	public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException 
                          	{
                          		handle(httpServletRequest,httpServletResponse,e);
                          	}
                          }
                          InvalidSessionHandler:

                          Code:
                           
                          
                          package com.smartgwt.sample.showcase.server.authentication;
                          
                          import java.io.IOException;
                          
                          import javax.servlet.ServletException;
                          import javax.servlet.http.HttpServletRequest;
                          import javax.servlet.http.HttpServletResponse;
                          
                          public interface InvalidSessionHandler {
                              void sessionInvalidated(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException;
                          }
                          web.xml

                          Code:
                           
                          <?xml version="1.0" encoding="UTF-8"?>
                          
                          <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
                                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
                                   version="2.4">
                          
                              <!-- standard spring configuration -->
                              <context-param>
                                  <param-name>contextConfigLocation</param-name>
                                  <param-value>/WEB-INF/applicationContext.xml</param-value>
                              </context-param>
                          
                          
                          
                              <context-param>
                                  <param-name>HSQLDB_CONFIG</param-name>
                                  <param-value>/WEB-INF/classes/hsqlserver.properties</param-value>
                              </context-param>
                          	
                          	<!-- 
                           <listener>
                                  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
                              </listener>-->
                              
                               <servlet>
                                  <servlet-name>context</servlet-name>
                                  <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
                                  <load-on-startup>1</load-on-startup>
                              </servlet>
                          
                             <!--
                                - Publishes events for session creation and destruction through the application
                                - context. Optional unless concurrent session control is being used.
                                -->
                              <listener>
                                <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
                              </listener>
                              <listener>
                                  <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
                              </listener>
                              <filter>
                                  <filter-name>springSecurityFilterChain</filter-name>
                                  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
                              </filter>
                              <filter-mapping>
                                  <filter-name>springSecurityFilterChain</filter-name>
                                  <url-pattern>/*</url-pattern>
                              </filter-mapping>
                          
                          
                          
                          
                              <!--start hsql db on startup for ease of use. Actualy database is located under WEB-INF/db/hsqldb-->
                              <listener>
                                  <listener-class>com.smartgwt.sample.showcase.server.listener.HSQLServletContextListener</listener-class>
                              </listener>
                          
                              <!-- Note: The servlets/filters referenced here are documented in the SDK javadoc -->
                          
                              <!-- //>FileLoader -->
                              <!-- Dynamic Compression -->
                              <filter>
                                  <filter-name>CompressionFilter</filter-name>
                                  <filter-class>com.isomorphic.servlet.CompressionFilter</filter-class>
                              </filter>
                              <!-- CompressionFilter for dynamic compression -->
                              <filter-mapping>
                                  <filter-name>CompressionFilter</filter-name>
                                  <url-pattern>/*</url-pattern>
                              </filter-mapping>
                              <!-- //<FileLoader -->
                          
                              <!-- 
                              <servlet>
                                  <servlet-name>context</servlet-name>
                                  <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
                                  <load-on-startup>1</load-on-startup>
                              </servlet>
                          	 -->
                          	 
                              <servlet>
                                  <servlet-name>showcase</servlet-name>
                                  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                                  <load-on-startup>1</load-on-startup>
                              </servlet>
                          
                              <!-- The IDACall servlet handles all Built-in DataSource operations -->
                              <servlet>
                                  <servlet-name>IDACall</servlet-name>
                                  <servlet-class>com.isomorphic.servlet.IDACall</servlet-class>
                              </servlet>
                          
                              <!-- The DataSourceLoader servlet returns Javascript representations of the dataSources whose
                                   ID's are passed to it - it is an alternative to using the <loadDS> JSP tag -->
                              <servlet>
                                  <servlet-name>DataSourceLoader</servlet-name>
                                  <servlet-class>com.isomorphic.servlet.DataSourceLoader</servlet-class>
                              </servlet>
                          
                              <!-- The FileDownload servlet downloads static files, like a webserver -->
                              <servlet>
                                  <servlet-name>FileDownload</servlet-name>
                                  <servlet-class>com.isomorphic.servlet.FileDownload</servlet-class>
                              </servlet>
                          
                              <!-- ISC init: initializes ISC framework -->
                              <servlet>
                                  <servlet-name>Init</servlet-name>
                                  <servlet-class>com.isomorphic.base.Init</servlet-class>
                                  <load-on-startup>1</load-on-startup>
                              </servlet>
                          
                              <servlet>
                                  <servlet-name>HttpProxy</servlet-name>
                                  <servlet-class>com.isomorphic.servlet.HttpProxyServlet</servlet-class>
                              </servlet>
                          
                              <!-- The PreCache servlet initializes when the servlet engine starts up and pre-loads 
                                   data need for all client requests.  This is optional, and improves performance
                                   of the first few page requests.  PreCache cannot be invoked by a browser, because
                                   there is no "servlet-mapping" defined for it. -->
                              <servlet>
                                  <servlet-name>PreCache</servlet-name>
                                  <servlet-class>com.isomorphic.servlet.PreCache</servlet-class>
                                  <load-on-startup>2</load-on-startup>
                              </servlet>
                          
                          
                              <servlet-mapping>
                                  <servlet-name>showcase</servlet-name>
                                  <url-pattern>*.do</url-pattern>
                              </servlet-mapping>
                          
                              <!-- RPCManager uses this URL by default for Built-in DataSource operations -->
                              <servlet-mapping>
                                  <servlet-name>IDACall</servlet-name>
                                  <url-pattern>/showcase/sc/IDACall/*</url-pattern>
                              </servlet-mapping>
                          
                              <!-- DataSourceLoader requests -->
                              <servlet-mapping>
                                  <servlet-name>DataSourceLoader</servlet-name>
                                  <url-pattern>/sc/DataSourceLoader</url-pattern>
                              </servlet-mapping>
                          
                              <servlet-mapping>
                                  <servlet-name>HttpProxy</servlet-name>
                                  <url-pattern>/showcase/sc/HttpProxy/*</url-pattern>
                              </servlet-mapping>
                          
                              <!-- Use FileDownload servlet to download all static content that's part of the skin, such as
                                   image files, so we can set Expires headers and other cache control directives.  In a
                                   production deployment, you'd want to use a webserver such as Apache to do this.  
                              -->
                              <servlet-mapping>
                                  <servlet-name>FileDownload</servlet-name>
                                  <url-pattern>/showcase/sc/skins/*</url-pattern>
                              </servlet-mapping>
                          
                              <!-- serve ISC modules compressed, with expires headers -->
                              <servlet-mapping>
                                  <servlet-name>FileDownload</servlet-name>
                                  <url-pattern>/showcase/sc/system/modules/*</url-pattern>
                              </servlet-mapping>
                          
                              <!-- serve ISC development modules compressed, with expires headers -->
                              <servlet-mapping>
                                  <servlet-name>FileDownload</servlet-name>
                                  <url-pattern>/showcase/sc/system/development/*</url-pattern>
                              </servlet-mapping>
                          
                              <!-- server skin assets with expires headers -->
                              <servlet-mapping>
                                  <servlet-name>FileDownload</servlet-name>
                                  <url-pattern>/showcase/sc/system/reference/skin/*</url-pattern>
                              </servlet-mapping>
                          
                              <!-- General config -->
                              <session-config>
                                  <session-timeout>30</session-timeout>
                              </session-config>
                          
                              <jsp-config>
                                  <!-- Isomorphic JSP tags -->
                                  <taglib>
                                      <taglib-uri>isomorphic</taglib-uri>
                                      <taglib-location>/WEB-INF/iscTaglib.xml</taglib-location>
                                  </taglib>
                              </jsp-config>
                          
                              <mime-mapping>
                                  <extension>csv</extension>
                                  <mime-type>text/csv</mime-type>
                              </mime-mapping>
                          
                              <mime-mapping>
                                  <extension>manifest</extension>
                                  <mime-type>text/cache-manifest</mime-type>
                              </mime-mapping>
                              
                          </web-app>
                          applicationContext.xml:

                          Code:
                           
                          
                          <?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"
                              xmlns:security="http://www.springframework.org/schema/security"
                              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">
                          
                          
                          
                          
                           <!-- SpringSecurity -->
                              <security:http entry-point-ref="authenticationEntryPoint">
                                  <security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter"/>
                                  <security:custom-filter position="FORM_LOGIN_FILTER" ref="formLoginFilter"/>
                                  <security:anonymous enabled="false"/>
                                  <security:intercept-url pattern="/showcase/sc/IDACall*" access="ROLE_USER"/>
                          
                                  <security:access-denied-handler ref="accessDeniedHandler"/>
                                  <security:session-management session-authentication-strategy-ref="sessionAuthenticationStrategy"/>
                              </security:http>
                          
                              <security:authentication-manager alias="authenticationManager">
                                  <security:authentication-provider>
                                      <security:user-service>
                                          <security:user name="test" authorities="ROLE_USER" password="test"/>
                                          <security:user name="guest" authorities="ROLE_USER" password="test"/>
                                      </security:user-service>
                                  </security:authentication-provider>
                              </security:authentication-manager>
                          
                              <beans:bean id="formLoginFilter"
                                    class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
                                  <beans:property name="sessionAuthenticationStrategy" ref="sessionAuthenticationStrategy"/>
                                  <beans:property name="authenticationManager" ref="authenticationManager"/>
                                  <beans:property name="authenticationSuccessHandler">
                                      <beans:bean class="com.smartgwt.sample.showcase.server.authentication.BiztrackAuthenticationSuccessHandler"/>
                                  </beans:property>
                                  <beans:property name="authenticationFailureHandler">
                                      <beans:bean class="com.smartgwt.sample.showcase.server.authentication.BiztrackAuthenticationFailureHandler"/>
                                  </beans:property>
                              </beans:bean>
                          
                              <beans:bean id="authenticationEntryPoint"
                                    class="com.smartgwt.sample.showcase.server.authentication.BiztrackAuthenticationEntryPoint"/>
                          
                              <beans:bean id="accessDeniedHandler"
                                    class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
                                  <beans:property name="errorPage" value="/accessDenied.htm"/>
                              </beans:bean>
                          
                              <beans:bean id="concurrencyFilter" class="com.smartgwt.sample.showcase.server.authentication.BiztrackConcurrentSessionFilter">
                                  <beans:property name="sessionRegistry" ref="sessionRegistry"/>
                                  <beans:property name="invalidSessionHandler">
                                      <beans:bean class="com.smartgwt.sample.showcase.server.authentication.BiztrackInvalidSessionHandler"/>
                                  </beans:property>
                              </beans:bean>
                          
                              <beans:bean id="sessionAuthenticationStrategy" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
                                  <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"/>
                                  <beans:property name="maximumSessions" value="1"/>
                              </beans:bean>
                              
                              <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
                          
                          
                            
                          
                            <!-- Transaction manager for supplyItemDMI -->
                            <beans:bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                              <beans:property name="sessionFactory" ref="hibernateSessionFactory"/>
                            </beans:bean>
                          
                            <!-- Hibernate SessionFactory -->
                            <beans:bean id="hibernateSessionFactory"
                                  class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                              <beans:property name="configLocation" value="classpath:hibernate.cfg.xml"/>
                                <!--mapping locations specified in hibernate.cfg.cml-->
                            </beans:bean>
                          
                          </beans:beans>

                          Comment


                            #28
                            Use the RPC tab of the Developer Console to check that you are actually sending the marker back to the browser, and check it very carefully for typos (for example, getting the quotes wrong, or similar).

                            Comment


                              #29
                              There are no requests on the RPC tab and I have Track RPC checked.

                              Would this be happening because this is an evaluation copy of SmartGWT?

                              Comment


                                #30
                                No.

                                The only explanation is that your code crashes before you even call RPCManager.sendRequest() (or you are somehow misusing the RPC tab..).

                                Comment

                                Working...
                                X