form-login配置中的authentication-success-handler-ref可以让手动注入登录成功后的处理程序,需要实现AuthenticationSuccessHandler接口。
登录成功之后的相关业务逻辑都可以写这个handler方法中,而不应该在login.do这种方法里写。
login.do应该仅处理验证登录、权限获取。
登录成功之后,使用handler来进行相关业务初始化操作。
先看配置:
<!-- 登录表单设置 --> <!-- login-page:登录页面 --> <!-- login-processing-url:自定义的登录提交action名称,需要与登录form中的action保持一致 --> <!-- authentication-failure-url:登录失败后跳转的页面 --> <!-- default-target-url:登录成功后跳转的页面,如果配置了authentication-success-handler-ref则不生效 --> <!-- username-parameter:登录用户名的参数名称,需要与登录form中的input name='username'保持一致 --> <!-- password-parameter:登录密码的参数名称,需要与登录form中的input name='password'保持一致 --> <!-- authentication-success-handler-ref:自定义登录成功后的Handler --> <sec:form-login login-page="/toLogin.do" login-processing-url="/login.do" authentication-failure-url="/toLogin.do?message=authentication-failure" authentication-success-handler-ref="customLoginSuccessHandler" username-parameter="username" password-parameter="password" />
自定义的successHandler
package com.fhzz.core.sercurity.handler; import java.io.IOException; import java.util.Date; 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.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.fhzz.core.sercurity.dao.SysUsersDao; import com.fhzz.core.sercurity.entity.SysUsers; import com.fhzz.core.utils.HTTPUtils; /** * @author YangYi * */ @Service public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler { Log logger = LogFactory.getLog(CustomLoginSuccessHandler.class); @Value("/toIndex.do") private String defaultTargetUrl; @Autowired private SysUsersDao sysUsersDao; @Override @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = { Exception.class }) public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { this.saveLoginInfo(request, authentication); logger.info("登录成功,即将forward:" + this.defaultTargetUrl); // 登录成功之后将SECURITY放入上下文中 request.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext()); request.getRequestDispatcher(this.defaultTargetUrl).forward(request, response); } private void saveLoginInfo(HttpServletRequest request, Authentication authentication) { SysUsers user = (SysUsers) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String ip = HTTPUtils.getIpAddress(request); user.setLastLogin(new Date()); user.setLoginIp(ip); logger.info("登录用户:" + user); this.sysUsersDao.saveOrUpdateSysUser(user); } }
这个handler 以记录用户登录信息为例,实现了onAuthenticationSuccess方法
实际上这里可以做任何应该与用户一同初始化的工作