您的位置:首页 > 编程语言 > Java开发

SpringMVC HandlerInterceptorAdapter登陆验证拦截器

2016-01-07 11:07 513 查看
工作中用到了验证用户是否登陆,判断是否有session值,想到了用SpringMVC HandlerInterceptorAdapter拦截器,方便,实用性大。

Spring MVC的拦截器不仅可实现Filter的所有功能,还可以更精确的控制拦截精度。

Spring为我们提供了org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,继承此类,可以非常方便的实现自己的拦截器。它有三个方法:

[code]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中配置的。

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

[code]@Controller
public 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);
    }
}


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

[code]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配置:

[code]<?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>


除了以上过滤的请求,其余全部会拦截,根据自己需求,进行更改。

可以根据这个配置多个拦截器,赋予它不同的分工。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: