Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security Custom Logout

I have a SpringBoot app that uses Spring security, but I want to customize it on authentication, but not authorization. I have done login successfully, but I have no idea where do I have to put my logout action. Here are some of my code: 1. The controller:

    @RequestMapping(value={"/login"}, method=RequestMethod.GET)
    public ModelAndView login(){

    return new ModelAndView("pages/login");

    }
  1. WebSecurityConfig

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        private @Autowired CustomAuthenticationProvider authenticationManager;
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
            .authorizeRequests()
                .anyRequest()
                    .authenticated()
                .and()
                .formLogin()
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .failureUrl("/login?error")
                    .defaultSuccessUrl("/")
                    .loginPage("/login")
                    .permitAll()
                .and()
                    .logout()
                    .logoutRequestMatcher(
                            new AntPathRequestMatcher("/login?logout")
                    ).logoutSuccessUrl("/login").permitAll()
                .and()
                .csrf().disable();
        }
    
        @Autowired
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.authenticationProvider( authenticationManager );
        }
    
        @Bean
        protected AuthenticationProvider getServicesAuthenticationProvider() {
        //stackoverflow.com/questions/22453550/custom-authentication-provider-not-being-called/22457561#22457561
             return new CustomAuthenticationProvider();
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring()
                    .antMatchers("/**/*.css")
                    .antMatchers("/**/*.js")
                    .antMatchers("/**/*.jpg")
                    .antMatchers("/**/*.png")
                    .antMatchers("/**/*.gif")
                    .antMatchers("/resources/**");
        }
        public PasswordEncoder passwordEncoder(){
            PasswordEncoder encoder = NoOpPasswordEncoder.getInstance();
            return encoder;
        }
    }
    
  2. CustomAuthenticationProvider

    @Component
    public class CustomAuthenticationProvider implements AuthenticationProvider{
        private static Logger logger = Logger.getLogger(CustomAuthenticationProvider.class);
        private @Autowired UAMSLogin uamsLogin;
        private Map<String, Boolean> userLoggedIn = new HashMap<String, Boolean>();
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String username = authentication.getPrincipal() + "";
            String password = authentication.getCredentials() + "";
            logger.info("authenticating....");
            if(username.equals("")|| username==null || password.equals("")|| password==null){
                logger.fatal("username or password cannot be empty!");
                return null;
            }
            else if(userLoggedIn.containsKey(username)){
                UsernamePasswordAuthenticationToken a = new UsernamePasswordAuthenticationToken(username, password);
                return a;
            }
            try {
                if (uamsLogin.loginUams(username, password)) {
                    logger.info("authentication success");
                    UamsSession sessionInfo = uamsLogin.getUams();
                    logger.info("authentication success");
                    String role = "USER";
                    userLoggedIn.put(username, true);
                    UsernamePasswordAuthenticationToken a = new UsernamePasswordAuthenticationToken(username, password);
                    return a;
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                logger.info("authentication failed");
                e.printStackTrace();
                throw new BadCredentialsException("1000");
            }
            return null;
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return authentication.equals(UsernamePasswordAuthenticationToken.class);
        }
    }
    
  3. UAMSLogin:

    @Component
    public class UAMSLogin implements Serializable {
    
    
        private static Logger logger = Logger.getLogger(UAMSLogin.class);
        private static final long serialVersionUID = 1L;
        private static boolean isConnected = false;
        private UamsSession session;
        @Value("${UAMS.SEC_SRV_CONN}")
        private String UAMS_SERVER_CONNECTION;
    
        @Value("${UAMS.CSM_SERVER_URL}")
        private String UAMS_CSM_SERVER_URL;
    
        @Value("${amdocs.ticketapplicationid}")
        private String amdocs_ticketapplicationid;
    
        @Value("${amdocs.ticketparam}")
        private String amdocs_ticketparam;  
        public UAMSLogin(){
    
        }
        // Login with UAMS
        public boolean loginUams(String username, String password) throws Exception {
            logger.info("loginUams with " + username + "/" + password);
            session = this.createSession();
            logger.info("create session success: "+session.toString());
            String ticket=null;
    
            logger.info("UamsSystem version: "+UamsSystem.getVersionString());
            try {
                session.ensureSession(username, password);
                ticket = session.getTicket();
                if (ticket != null && ticket !="") {
                    logger.info("login success : " + session.getTicket());
                    isConnected = true;
                    return true;
                } else {
                    logger.info("login failed: ticket is NULL");
                    return false;
                }
            } catch (Exception e) {
                logger.info("login failed: ", e);
                return false;
            }
        }
    
        protected UamsSession createSession() throws Exception {
            UamsSession session     = new UamsSession(ReadConfig.readInputStream());
    
            logger.info("UAMS_SERVER_CONNECTION: "+UAMS_SERVER_CONNECTION);
            logger.info("UAMS_CSM_SERVER_URL: "+UAMS_CSM_SERVER_URL);
            logger.info("amdocs_ticketapplicationid: "+amdocs_ticketapplicationid);
            logger.info("amdocs_ticketparam:  "+amdocs_ticketparam);
            session.setSecurityUrl(UAMS_SERVER_CONNECTION);
            session.setProviderUrl(UAMS_CSM_SERVER_URL);
    
            session.setApplicationId(amdocs_ticketapplicationid);
            session.setParam(amdocs_ticketparam);
            return session;
        }
    
        public static boolean isConnected() {
            return isConnected;
        }
    
    
        public UamsSession getUams(){
            return session;
        }
    
    }
    

As you can see I am using UAMS to see if this user valid or not. I still don't know how to remember each session, so as you can see there are dirty code HashMap containsKey. More importantly, if I make session.logout(username); where should I call that?? UAMS is a Jar that used on my company.

If you find this question is not clear I'm very sorry and please ask me. Any help will be greatly appreciated.

like image 263
Shofwan Avatar asked Apr 01 '26 07:04

Shofwan


1 Answers

If I understand, I guess you want to perform some action on the UAMS library you talked about once the logout is done in Spring Security.

If this is what you are talking about, I would better do it using a custom LogoutSuccessHandler and binding it in your config to the logout action.

LogoutSuccessHandler interface has just a method you should implement:

public class CustomLogoutHandler implements LogoutSuccessHandler {

    private Logger logger = Logger.getLogger(this.getClass());

    /* (non-Javadoc)
     * @see org.springframework.security.web.authentication.logout.LogoutSuccessHandler#onLogoutSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication)
     */
    @Override
    public void onLogoutSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {

        logger.debug("CustomLogoutHandler.onLogoutSuccess");

    }

}

Here you could do wathever you need and then even redirect to any page you should go to after session logout.

EDIT:

You should use a LogoutSuccessHandler as I said or even better add a LogoutHandler:

public class TaskImplementingLogoutHandler implements LogoutHandler {

    /* (non-Javadoc)
     * @see org.springframework.security.web.authentication.logout.LogoutHandler#logout(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.Authentication)
     */
    @Override
    public void logout(HttpServletRequest req, HttpServletResponse res,
            Authentication authentication) {
        // do whatever you need
    }

} 

Once you implemented the LogoutHandler that fits your needs, you should add it to your configuration. Have a look at the java security configuration logout section

Your java security config must be like this:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
            .anyRequest()
                .authenticated()
            .and()
            .formLogin()
                .usernameParameter("username")
                .passwordParameter("password")
                .failureUrl("/login?error")
                .defaultSuccessUrl("/")
                .loginPage("/login")
                .permitAll()
            .and()
                .logout()
                .logoutRequestMatcher(
                        new AntPathRequestMatcher("/login?logout")
                )
                .addLogoutHandler(new TaskImplementingLogoutHandler())
                .logoutSuccessUrl("/login").permitAll()
            .and()
            .csrf().disable();
    }
like image 176
jlumietu Avatar answered Apr 09 '26 22:04

jlumietu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!