基于Token登入

REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

1.基于Session登录验证(有会话状态)

用户发出登录请求,带着用户名和密码到服务器验证,服务器验证成功就将用户信息写入到Session中。后续用户再请求就可以查看Session中有没有登录信息,有就允许登入或者继续操作,没有就返回到登入界面

2.基于Token登录验证(无会话状态)

用户发出登录请求,带着用户名和密码到服务器经行验证,服务器验证成功就在后台生成一个令牌返回给客户端,客户端把这个令牌储存起来(浏览器可以存储到Cookie中,服务端可以存放到Session,数据库,Redis中),redis可以设置存储令牌的有效期。后续的每次操作客户端都需要带着令牌发出请求,服务器会对令牌进行检测,(比如说)成功允许继续操作,时报就返回到登录界面。

令牌管理:生成令牌、有效期管理、销毁令牌。

令牌号:可以使用JWT生成令牌,使用用户ID生成令牌

有效期:使用Redis key有效期设置(每次操作完了都会更新延长有效时间)

销毁令牌:清空Redis

令牌存储:客户端(Cookie)、服务端(Redis)

Cookie的存取操作(js插件)

Redis存取(RedisTemplate操作)

具体代码

    1.令牌类

生成Token

使用UUID算法工具类随机生成一个不重复的随机值,再加上userid组合成Token字符串,存入Redis并返回

检查Token

解析出userid和uuid(首先保证非空,按_拆分,判断格式),根据Redis进行检查(去除redis中的Token和key比较),再更新Token时间,返回检测结果。

销毁Token

检查一个token是否正确,解析出userid和uuid(首先保证非空,按_拆分,判断格式)根据Redis进行检查(去除redis中的Token和key比较),再删除Token。

@Component
public class TokenManager {
	
	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
	
	/**
	 * 生成一个令牌
	 * @param userId 用户ID
	 * @return 返回令牌
	 */
	public String createToken(int userId){
		//生成token
		UUID uuid = UUID.randomUUID();
		String token = userId+"_"
			+uuid.toString().replaceAll("-", "");
		//将token存入redis
		String key = userId+"_token";
		redisTemplate.opsForValue().set(key, token, 
			Constants.TOKEN_EXPIRE_HOUR, TimeUnit.HOURS);
		return token;
	}
	
	/**
	 * 检查token是否正确
	 * @param token 令牌
	 * @return true正确;false失败
	 */
	public boolean checkToken(String token){
		//解析出userId和uuid
		if(token==null || "".equals(token)){
			return false;
		}
		String[] arr1 = token.split("_");
		if(arr1.length != 2){
			return false;
		}
		//根据redis进行检查
		String key = arr1[0]+"_token";
		String r_token = (String)redisTemplate.opsForValue().get(key);
		if(r_token==null){
			return false;
		}
		if(!token.equals(r_token)){
			return false;
		}
		//返回检测结果,更新token时间
		redisTemplate.opsForValue().set(key, token, 
				Constants.TOKEN_EXPIRE_HOUR, TimeUnit.HOURS);
		return true;
	}
	
	/**
	 * 注销Token
	 * @param token 令牌
	 * @return true正确;false失败
	 */
	public boolean clearToken(String token){
		//解析出userId和uuid
		if(token==null || "".equals(token)){
			return false;
		}
		String[] arr1 = token.split("_");
		if(arr1.length != 2){
			return false;
		}
		//根据redis进行检查
		String key = arr1[0]+"_token";
		String r_token = (String)redisTemplate.opsForValue().get(key);
		if(r_token==null){
			return false;
		}
		//注销token
		redisTemplate.delete(key);
		return true;
	}
	
	public static void main(String[] args){
		TokenManager manager = new TokenManager();
		System.out.println(manager.createToken(1));
	}
	
}
测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes={BootApplication.class})
public class TestTokenManager {

	@Autowired
	private TokenManager manager;
	
	@Test
	public void test1(){
		String token = manager.createToken(1);
		System.out.println(token);
	}
	
	@Test
	public void test2(){
		boolean ok = manager.checkToken("1_add8f21134984c3fab898f9451acaa03");
		System.out.println(ok);
	}
	
}

用户的接口类
public interface UserService {
	
	public ResponseEntity checkLogin(String username,String password);
	
}



用户接口类的实现
@Service
public class UserServiceImpl implements UserService{

	@Autowired
	private UserMapper userMapper;
	
	@Autowired
	private TokenManager tokenManager;
	
	@Override
	public ResponseEntity checkLogin(String username, String password) {
		ResponseEntity response = new ResponseEntity();
		//检测用户
		User user = userMapper.selectByName(username);
		if(user == null){
			response.setStatus(2);
			response.setMsg("用户错误");
		} else if(!user.getPassword().equals(password)){
			//检测密码
			response.setStatus(3);
			response.setMsg("密码错误");
		}else{ 
			//成功
			response.setStatus(1);
			response.setMsg("登录成功");
			String token = tokenManager.createToken(user.getId());
			response.setData(token);
		}
		return response;
	}

}
UserController
@RestController
public class UserController {

	@Autowired
	private UserService userService;
	
	@RequestMapping(value="/user/token",method=RequestMethod.POST)
	public ResponseEntity login(String username,String password){
		return userService.checkLogin(username, password);
	}
	
}
单体测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes={BootApplication.class})
@WebAppConfiguration//启动tomcat
public class TestUserController {

	@Autowired
	private UserController userController;
	
	//发送MVC请求,获取响应结果
	MockMvc mockMvc = null;
	
	@Before//每次执行@Test方法前都会调用init方法
	public void init(){
		mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
	}
	
	@Test//登录成功
	public void test1() throws Exception{
		//发送一个post请求
		MockHttpServletRequestBuilder postRequest = 
			MockMvcRequestBuilders.post("/user/token")
		.param("username", "scott")
		.param("password", "123456");
		//执行请求
		MvcResult result = mockMvc.perform(postRequest).andReturn();
		//获取返回结果内容
		String body = result.getResponse().getContentAsString();
		System.out.println(body);
	}
	
	@Test//用户错误
	public void test2() throws Exception{
		//发送一个post请求
		MockHttpServletRequestBuilder postRequest = 
			MockMvcRequestBuilders.post("/user/token")
		.param("username", "scott1")
		.param("password", "123456");
		//执行请求
		MvcResult result = mockMvc.perform(postRequest).andReturn();
		//获取返回结果内容
		String body = result.getResponse().getContentAsString();
		System.out.println(body);
	}
	
	@Test//密码错误
	public void test3() throws Exception{
		//发送一个post请求
		MockHttpServletRequestBuilder postRequest = 
			MockMvcRequestBuilders.post("/user/token")
		.param("username", "scott")
		.param("password", "12345");
		//执行请求
		MvcResult result = mockMvc.perform(postRequest).andReturn();
		//获取返回结果内容
		String body = result.getResponse().getContentAsString();
		System.out.println(body);
	}
	
}



评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值