移动大脑-SpringMVc搭建RestFul后台服务(四)-添加Token拦截器

本文介绍如何在SpringMVC搭建的RestFul服务中实现Token验证功能,包括实体类定义、DAO层实现、拦截器编写及Service层处理,确保API的安全调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

我的视频课程(基础):《(NDK)FFmpeg打造Android万能音频播放器》

我的视频课程(进阶):《(NDK)FFmpeg打造Android视频播放器》

我的视频课程(编码直播推流):《Android视频编码和直播推流》

 

目录:

 

        移动大脑-SpringMVc搭建RestFul后台服务(一)-环境搭建

        移动大脑-SpringMVc搭建RestFul后台服务(二)-配置mysql数据库

        移动大脑-SpringMVc搭建RestFul后台服务(三)-RestFul接口编写(模拟用户注册登录)

        移动大脑-SpringMVc搭建RestFul后台服务(四)-添加Token拦截器

        移动大脑-SpringMVc搭建RestFul后台服务(五)-支付宝支付

        移动大脑-SpringMVc搭建RestFul后台服务(六)-微信支付(Android)        

        移动大脑-SpringMVc搭建RestFul后台服务(七)-增量更新

 

        在第三篇博客《移动大脑-SpringMVc搭建RestFul后台服务(三)-RestFul接口编写(模拟用户注册登录)》中我们已经可以通过客户端访问服务端数据了,现在还需要添加Token验证功能来达到一定的安全性,此时就需要用到拦截器——HandlerInterceptor。

一、添加TokenBean.java实体类和表t_token

 

package com.ywl5320.appservice.bean;

/**
 * Created by ywl5320 on 2017/10/13.
 */
public class TokenBean extends BaseBean{

    private Integer id;
    private String phone;
    private String token;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }
}

在entitis.hbm.xml中配置表t_token:

 

 

<class name="com.ywl5320.appservice.bean.TokenBean" table="t_token">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="phone" column="phone"></property>
        <property name="token" column="token"></property>
    </class>

 

 

二、添加TokenDao.java和TokenDaoImpl.java

TokenDao.java

 

package com.ywl5320.appservice.dao;

import com.ywl5320.appservice.bean.TokenBean;

/**
 * Created by ywl5320 on 2017/10/13.
 */
public interface TokenDao {

    /**
     * 登录或注册时写入token
     * @param tokenBean
     */
    void saveOrUpdageToken(TokenBean tokenBean);

    /**
     * 根据电话号码获取token
     * @param phone
     * @return
     */
    TokenBean isTokenAvailable(String phone);

}

TokenDaoImpl.java

 

 

package com.ywl5320.appservice.dao;

import com.ywl5320.appservice.bean.TokenBean;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;

import java.util.List;

/**
 * Created by ywl5320 on 2017/10/13.
 */
public class TokenDaoImpl extends HibernateDaoSupport implements TokenDao{

    public void saveOrUpdageToken(TokenBean tokenBean) {
        this.getHibernateTemplate().saveOrUpdate(tokenBean);
    }

    public TokenBean isTokenAvailable(String phone) {
        List<TokenBean> tokens = (List<TokenBean>) this.getHibernateTemplate().find("from TokenBean where phone=?", phone);
        if(tokens != null && tokens.size() > 0)
        {
            return tokens.get(0);
        }
        return null;
    }
}

这样存储token和获取token都完成了。

 

最后配置TokenDaoImplement到beans.xml中

 

<bean id="tokenDaoImpl" class="com.ywl5320.appservice.dao.TokenDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

 

三、拦截器的编写,客户端把token、phone等信息放在header里面,服务端在收到请求的第一步就先判断header中token和phone是否匹配,然后做相应的处理:

RestFulInterceptor.java

 

package com.ywl5320.appservice.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ywl5320.appservice.bean.RestFulBean;
import com.ywl5320.appservice.bean.TokenBean;
import com.ywl5320.appservice.dao.TokenDao;
import com.ywl5320.appservice.util.RestFulUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Writer;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ywl5320 on 2017/10/16.
 */
public class RestFulInterceptor implements HandlerInterceptor {

	@Autowired
	private TokenDao tokenDao;
	
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
		// TODO Auto-generated method stub
		
		String uri = request.getRequestURI();
		Map<String, String> headerMaps = new HashMap<String, String>();
	    Enumeration headerNames = request.getHeaderNames();
	    while (headerNames.hasMoreElements()) {
	        String key = (String) headerNames.nextElement();
	        String value = request.getHeader(key);
	        headerMaps.put(key, value);
	    }
	    if(!uri.endsWith(".do"))
	    {
	    	return true;
	    }
	    if(uri.endsWith("user/loginbypwd.do"))//登录
		{
			return true;
			
		}
		else if(uri.endsWith("user/register.do"))//注册
		{
			return true;
		}
		else if(uri.endsWith("pay/verifyalipayresult.do"))//支付验证(暂留)
		{
			return true;
		}
		else
		{
			TokenBean tokenBean = tokenDao.isTokenAvailable(headerMaps.get("phone"));
			if(tokenBean != null && tokenBean.getToken().equals(headerMaps.get("token")))
			{
				return true;
			}
			else
			{
				RestFulBean<TokenBean> resuFulBean = RestFulUtil.getInstance().getResuFulBean(null, 1, "用户身份验证失败");
				response.setCharacterEncoding("UTF-8");
				Writer writer = response.getWriter();
				writer.write(JSONObject.toJSONString(resuFulBean, SerializerFeature.WriteMapNullValue));
				return false;
			}
		}
	}
	
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
	}
	
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
	}
	
}

验证里面有登录和注册接口不需要验证,其他不是以.do结尾的也不需要验证(可根据时间情况调整),还有支付回调(后面添加)也不需要验证。

 

最后在springmvc.xml中配置拦截器:

 

<mvc:interceptors>
        <bean class="com.ywl5320.appservice.interceptor.RestFulInterceptor"/>
    </mvc:interceptors>

四、在Service的注册和登录接口中生成和返回token并添加一个需要验证Token的获取用户详情的接口用来测试。

 

UserService.java

 

package com.ywl5320.appservice.service;

import com.ywl5320.appservice.bean.RestFulBean;
import com.ywl5320.appservice.bean.TokenBean;
import com.ywl5320.appservice.bean.UserBean;
import com.ywl5320.appservice.dao.TokenDao;
import com.ywl5320.appservice.dao.UserDao;
import com.ywl5320.appservice.util.MD5;
import com.ywl5320.appservice.util.RestFulUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by ywl5320 on 2017/10/12.
 */
@Transactional
public class UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private TokenDao tokenDao;

    public RestFulBean<UserBean> registorServer(UserBean userBean)
    {
        UserBean user = userDao.getUser(userBean.getPhone());
        if(user != null)
        {
            return RestFulUtil.getInstance().getResuFulBean(null, 1, "已经注册过了");
        }
        else
        {

            user = userDao.registor(userBean);
            if(user != null)
            {
                saveOrUpdateToken(user);
                return RestFulUtil.getInstance().getResuFulBean(user, 0, "注册成功");
            }
            else{
                return RestFulUtil.getInstance().getResuFulBean(null, 1, "注册失败");
            }
        }

    }

    public RestFulBean<UserBean> login(String phone, String password)
    {
        UserBean user = userDao.login(phone, password);
        if(user != null)
        {
            saveOrUpdateToken(user);
            return RestFulUtil.getInstance().getResuFulBean(user, 0, "登录成功");
        }
        else
        {
            return RestFulUtil.getInstance().getResuFulBean(null, 1, "用户不存在");
        }
    }

    public RestFulBean<UserBean> userinfo(String phone)
    {
        UserBean userBean = userDao.getUser(phone);
        if(userBean != null)
        {
            return RestFulUtil.getInstance().getResuFulBean(userBean, 0, "获取成功");
        }
        return RestFulUtil.getInstance().getResuFulBean(null, 1, "用户不存在");
    }

    private void saveOrUpdateToken(UserBean userBean){
        String token = null;
        try {
            token = MD5.encryptMD5(String.valueOf(System.currentTimeMillis()) + "appservice.02154778ke783dad34");
        } catch (Exception e) {
            e.printStackTrace();
        }
        userBean.setToken(token);
        TokenBean tokenBean = tokenDao.isTokenAvailable(userBean.getPhone());
        if(tokenBean != null)
        {
            tokenBean.setToken(token);
        }
        else
        {
            tokenBean = new TokenBean();
            tokenBean.setPhone(userBean.getPhone());
            tokenBean.setToken(userBean.getToken());
        }
        tokenDao.saveOrUpdageToken(tokenBean);
    }

}

五、UserAction中添加Get方法获取用户详情

 

 

/**
     * 详情
     * @param phone
     * @return
     */
    @ResponseBody
    @RequestMapping(value="/userinfo.do", method= RequestMethod.GET)
    public RestFulBean<UserBean> userInfo(String phone)
    {
        System.out.println("phone:" + phone);
        return userService.userinfo(phone);
    }

以上就为服务端的接口添加了Token的拦截器,达到了一定的安全性,这里没有设定token的过期时间,可以再加一个token过期时间(实际情况主要还是根据需求来)。

 

 

六、最后用客户端测试一下(客户端是基于我的另一个GitHubRxjavaRetrofit 项目修改而来的):

6.1:当没有登录时获取详情,此时token为空,验证失败

由于是get请求,我们也可以直接在浏览器中测试:

结果表明还是不能通过身份验证。

6.2执行用户登录操作:

测试表明登录接口能正常访问,并没有验证并返回了token给客户端,注册和支付回调接口也是一样的不用验证。

6.3、再执行获取详情接口

现在就可以正常获取用户数据了。

 

源码下载:GitHub AppServiceRestFul 

这样一个完整的RestFul实例就完成了配合客户端就能完成一个功能健全的应用程序了。

接下来几篇博客来提高一下综合功能(支付、增量更新等)。


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ywl5320

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值