前后端分离:WebAPI+Vue开发——远程数据请求axios

前后端分离:WebAPI+Vue开发——跨域设置

前后端分离:WebAPI+Vue开发——身份认证

存储用户身份可以用Cache内存或者Redis,本文实现用的是Redis。

1、在登录页或者首页页面打开后,先获取Token用户身份

在首页或者登录页加载完成后,远程请求服务端,获取服务端生成的token,本文的Token用guid生成,服务端实现如下:

/// <summary>
/// 获取token
/// </summary>
/// <returns></returns>
[HttpGet]
public object GetToken()
{
	try
	{
		Result result = new Result();
		result.ret = 1;
		var req = Request.Headers.GetValues("token");
		string token = req.FirstOrDefault();
		if (!string.IsNullOrEmpty(token))//已存在token
		{
			string key = "user:" + token;
			if (RedisHelper.KeyExists(key))//表示用户是登录状态
			{
				result.ret = 2;
			}
		}
		else
		{
			token = Guid.NewGuid().ToString();
		}
		result.data = token;
		return result;
	}
	catch (Exception ex)
	{
		return ex.Message;
	}
}

2、客户端添加验证

客户端获取token值并存储本地cookie,并设置1个小时的有效期,之后页面加载时都判断是否存在token,存在则更新cookie的有效期,不存在则跳转到首页,然后在首页获取token。上面的操作最好是放在一个js公共文件中,在每个页面都引用,涉及到敏感信息的远程请求时,都在请求 头中携带这个token。

JS代码如下:

//用户登录状态检查,未登录转首页
var token = getCookie('token');
if (!token && location.href != 'http://www.abc.com/') {
    location.href = '/';
} 
if(token){
    setCookie('token', token, 60 * 60);
}

3、在服务端存储用户身份信息

用户进行登录操作时,将token数据也发送到服务端,用户登录成功后,以token以键,把用户信息存储在Cache内存或者Redis中,同时设置用户信息的有效期,注意:redis中数据的有效期要与客户端cookie的有效期同步或者时间略长。登录验证码的功能此处不再实现

/// <summary>
/// 登录接口
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
[HttpPost]
public object Login(dynamic data)
{
	var req = Request.Headers.GetValues("token");
	try
	{
		Result result = new Result();
		string token = req.FirstOrDefault();
		string name = Convert.ToString(data.name);
		string pwd = Convert.ToString(data.pwd);
		Entities db = new Entities();
		var userinfo = db.UserInfo.Where(u => u.UserName == name.Trim()).FirstOrDefault();
		if (userinfo != null && userinfo.Id > 0)//存在该用户
		{
			if (userinfo.UserPwd == pwd.Trim())//登录成功
			{
				string user_key = "user:" + token;
				RedisHelper.String_set(user_key, JsonConvert.SerializeObject(userinfo), 60 * 60);//将用户信息存储在redis里边
				result.ret = 1;
			}
			else
			{
				result.ret = 5;
				result.msg = "密码输入错误,请仔细核对";
			}
		}
		else
		{
			result.ret = 4;
			result.msg = "该用户不存在,请检查用户名";
		}
		return result;
	}
	catch (Exception ex)
	{
		return new Result
		{
			ret = -1,
			msg = ex.Message,
			data = ""
		};
	}
}

4、服务端验证Token的有效性

之后的请求,涉及到数据的操作时,每次请求都需要验证请求的合法性,即验证Token的有效性。在WebAPI中,添加一个基类BaseController,需要验证用户身份的Controller都继承基类,在基类中添加Http请求的Header验证,如果header中存在token,并且redis中也有该token的用户信息,则进行后续操作,如果不存在,返回错误状态,前端跳转重新登录的页面。

基类BaseController如下:

public class BaseController : ApiController
{
	public string token = "";
	public UserInfo user = null;
	protected override void Initialize(HttpControllerContext controllerContext)
	{
		//初始化请求上下文
		base.Initialize(controllerContext);
		var req = Request.Headers.GetValues("token");
		token = req.FirstOrDefault();
		if (!string.IsNullOrEmpty(token))
		{
			string user_key = "user:" + token;
			if (Common.RedisHelper.KeyExists(user_key))//判断redis中是否存储的有该用户的信息
			{
				string json = Common.RedisHelper.String_get(user_key);
				user = JsonConvert.DeserializeObject<UserInfo>(json);//反序列化UserInfo
				Common.RedisHelper.ExpireKey(user_key, 60 * 60);//更新redis中用户信息的过期时间
			}
		}
	}
}