SpringMVC HandlerInterceptorAdapter登陆验证拦截器

来源:互联网 发布:移动协同软件下载 编辑:程序博客网 时间:2024/04/30 02:32

工作中用到了验证用户是否登陆,判断是否有session值,想到了用SpringMVC HandlerInterceptorAdapter拦截器,方便,实用性大。
Spring MVC的拦截器不仅可实现Filter的所有功能,还可以更精确的控制拦截精度。
Spring为我们提供了org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,继承此类,可以非常方便的实现自己的拦截器。它有三个方法:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)          throws Exception {          return true;  }  public void postHandle(          HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)          throws Exception {  }  public void afterCompletion(          HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)          throws Exception {  } 

分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。

如果基于xml配置使用Spring MVC,
可以利用SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping进行Url映射(相当于struts的path映射)和拦截请求(注入interceptors),
如果基于注解使用Spring MVC,可以使用DefaultAnnotationHandlerMapping注入interceptors。
注意无论基于xml还是基于注解,HandlerMapping bean都是需要在xml中配置的。

我做的功能是用户登录验证,代码如下:

@Controllerpublic class SessionInjectionInterceptor extends HandlerInterceptorAdapter {    private static Logger log = Logger            .getLogger(SessionInjectionInterceptor.class);    @Autowired    private HttpSession session;    @Autowired    private ILoginService loginService;    public boolean preHandle(HttpServletRequest request,            HttpServletResponse response, Object handler) throws Exception {        // 获取当前登录人信息        Authentication authentication = SecurityContextHolder.getContext()                .getAuthentication();        // 判断当前用户session为null,并且已经做了登陆验证。        if (authentication != null                && session                        .getAttribute(Constants.Session.ACCOUNT_ATTRIBUTE_NAME) == null) {            String username = authentication.getName();            if (!"anonymousUser".equals(username)) {                // account                Account account = (Account) loginService                        .getAccountByName(username);                session.setAttribute(Constants.Session.ACCOUNT_ATTRIBUTE_NAME,                        account);            } else {                // 做无浏览权限验证,或者未登陆用户,转发到登陆页面                session.setAttribute(Constants.Session.ACCOUNT_ATTRIBUTE_NAME,                        null);                request.getRequestDispatcher("/login.jsp").forward(                        request, response);                return false;            }        }        return super.preHandle(request, response, handler);    }}

用户登录验证,和前台页面配合:

public class CustomAuthenticationProvider implements AuthenticationProvider {    private static Logger log = Logger            .getLogger(CustomAuthenticationProvider.class);    private JdbcTemplate jdbcTemplate;    public void setDataSource(DataSource dataSource) {        this.jdbcTemplate = new JdbcTemplate(dataSource);    }    @Override    public Authentication authenticate(Authentication authentication)            throws AuthenticationException {        // 获取前台传送的用户名和密码        String username = authentication.getName();        String password = authentication.getCredentials().toString();        log.debug("username = " + username + " password = " + password);        // 根据用户名密码查询用户是否存在,并返回编码值        UserResult ur = authorize(username, password);        log.debug(ur.toJson());        // 判断编码值是否是success,        if (ur.getCode().equals(UserResult.Code.SUCCESS)) {            List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();            grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));            return new UsernamePasswordAuthenticationToken(username, password,                    grantedAuths);        } else {            throw new AuthenticationException(ur.getMsg().getContent()) {                private static final long serialVersionUID = -5506038021601762240L;            };        }    }    @Override    public boolean supports(Class<?> authentication) {        return authentication.equals(UsernamePasswordAuthenticationToken.class);    }    private UserResult authorize(final String name, final String password) {        log.info("authorize begin. name = " + name);        if (name == "" || null == name) {            return new UserResult(Code.FAIL, Msg.ILLEGAL_USERNAME);        }        // TODO 根据名称查询用户是否存在,暂用自己测试        String sql = "select * from ACCOUNT where LLOGIN_ID = ? and PPASSWORD = ?";        Object[] params = { name,password };        Account account = null;        try {            account = jdbcTemplate.queryForObject(sql, params, new BeanPropertyRowMapper<Account>(Account.class));            // 判断根据用户名查找用户是否存在            if (null == account) {                log.info("username 是不存在的名字 = " + name);                return new UserResult(Code.FAIL, Msg.USER_NOT_EXIST);            }        } catch (Exception e) {            log.error(e, e);            if (e instanceof IncorrectResultSizeDataAccessException) {                // 没有结果,或者结果数据不符合                account = null;                log.info("username 是不存在的名字 = " + name);                return new UserResult(Code.FAIL, Msg.USER_NOT_EXIST);            } else {                return new UserResult(Code.FAIL, Msg.DATA_ACCESS_EXCEPTION);            }        }        log.debug("authorize end.");        return new UserResult(Code.SUCCESS, Msg.SUCCESS);    }}

XML配置:

<?xml version="1.0" encoding="UTF-8"?><beans:beans xmlns="http://www.springframework.org/schema/security"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">    <beans:bean id="propertyConfigurer"        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">        <beans:property name="location" value="classpath:c3p0.properties"/>    </beans:bean>    <beans:bean id="securityDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">        <beans:property name="driverClass" value="com.mysql.jdbc.Driver" />        <beans:property name="jdbcUrl" value="${jdbc.url}" />        <beans:property name="user" value="${jdbc.username}" />        <beans:property name="password" value="${jdbc.password}" />    </beans:bean>    <!-- 用户登录验证 -->     <beans:bean class="com.impl.CustomAuthenticationProvider" id="customAuthenticationProvider">        <beans:property name="dataSource" ref="securityDataSource" />    </beans:bean>       <!-- 配置静态页面 -->     <http pattern="/fonts/**" security="none"/>    <http pattern="/js/**" security="none"/>    <http pattern="/css/**" security="none"/>    <http pattern="/images/**" security="none"/>    <!-- 配置不拦截的请求 -->    <http auto-config="true" use-expressions="true" create-session="ifRequired">        <intercept-url pattern="/login" access="permitAll" />        <intercept-url pattern="/proxy/*" access="permitAll" />        <intercept-url pattern="/register" access="permitAll" />        <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />        <form-login login-page="/login"  default-target-url="/homePage" always-use-default-target="true" />                     <logout invalidate-session="true"  logout-success-url="/homePage" logout-url="/j_spring_security_logout"/>      </http>     <authentication-manager>        <authentication-provider ref="customAuthenticationProvider" />    </authentication-manager></beans:beans>

除了以上过滤的请求,其余全部会拦截,根据自己需求,进行更改。
可以根据这个配置多个拦截器,赋予它不同的分工。

0 0
原创粉丝点击