简体   繁体   中英

Customize login in Grails Spring Security plugin

I have an application where the login should include an organization number, so the login needs to be username + password + organization number .

Sample case: If the username + password matches with an existing user, I need to check if that user has the organization id. If not, the login should fail.

I saw that the login form from spring security plugin submits to /app/j_spring_security_check but couldn't find where that is actually implemented.

Also I'm not sure if touching that is the right way of implementing this custom login.

My question is where / how to customize the login action? (to make it fail on the case I described above).

We can do this by overriding the filter UserNamePasswordAuthenticationFilter and provide our custom attemptAuthentication. So, go to DefaultSecurityConfig.groovy file (inside plugins). See tree diagram below:

  target
      |-work
            |-plugins
                    |-spring-security-core-2.0-RC5
                                          |-conf
                                               |-DefaultSecurityConfig.groovy

In DefaultSecurityConfig.groovy under apf closure we specify filterProcessUrl which we can override in grails application's Config.groovy like we do for other properties (eg rejectIfNoRule)

grails.plugin.springsecurity.apf.filterProcessesUrl="your url"

Now we understood how it checks for authentication.Let's customise it own way by overriding the method attemptAuthentication of filter named UsernamePasswordAuthenticationFilter . For example, see below(also, go through the inline comments added there)

 package org.springframework.security.web.authentication;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.security.authentication.AuthenticationServiceException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
    import org.springframework.util.Assert;

    public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
        public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
        public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
        /** @deprecated */
        @Deprecated
        public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
        private String usernameParameter = "j_username";
        private String passwordParameter = "j_password";
        private String organisationParameter = 'j_organisation'
        private boolean postOnly = true;

        public UsernamePasswordAuthenticationFilter() {
            super("/j_spring_security_check");
        }

        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            if(this.postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
            } else {
                String username = this.obtainUsername(request);
                String password = this.obtainPassword(request);
                String password = this.obtainOrganisation(request);

              //regular implementation in spring security plugin   /**
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                this.setDetails(request, authRequest);
                return         this.getAuthenticationManager().authenticate(authRequest);
            }
**/

//Your custom implementation goes here(Authenticate on the basis of organisation as well). Here you need to customise authenticate as per your requirement so that it checks for organisation as well.
        }

       protected String obtainOrganisation(HttpServletRequest request) {
        return request.getParameter(this.organisationParameter);
    }    

        protected String obtainPassword(HttpServletRequest request) {
            return request.getParameter(this.passwordParameter);
        }

        protected String obtainUsername(HttpServletRequest request) {
            return request.getParameter(this.usernameParameter);
        }

        protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
            authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
        }

        public void setUsernameParameter(String usernameParameter) {
            Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
            this.usernameParameter = usernameParameter;
        }

        public void setPasswordParameter(String passwordParameter) {
            Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
            this.passwordParameter = passwordParameter;
        }

        public void setPostOnly(boolean postOnly) {
            this.postOnly = postOnly;
        }

        public final String getUsernameParameter() {
            return this.usernameParameter;
        }

        public final String getPasswordParameter() {
            return this.passwordParameter;
        }
    }

Hence, it's more of a overriding task in terms of spring security.

To get more clearer idea about same read this nice link for java and for grails read this

Hope it helps.

These blogs gives a more detailed idea of the same requirements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM