使用场景
现在很多基于restful的api接口都有个登录的设计,也就是在发起正式的请求之前先通过一个登录的请求接口,申请一个叫做token的东西。申请成功后,后面其他的支付请求都要带上这个token,服务端通过这个token验证请求的合法性。这个token通常都有一个有效期,一般就是几个小时。
在比如微信的公众平台接口,关键的接口在使用之前都要带access token。access_token是公众号的全局唯一票据,有效期为7200秒,重复获取将导致上次获取的access_token失效。
Redis的安装配置 (docker)
docker pull redis
docker run --name redis -d -p 6379:6379 redis:latest
springboot项目
1.在新建项目的时候,选择redis相关依赖
2.在application.yml (这里使用yml) 配置redis参数
spring:
redis:
host: 192.168.147.129
port: 6379
3.redis常数实体类
package com.example.demo.bean;
/**
* Created by Administrator on 2017/12/11 0011.
*/
public interface RedisConstant {
String TOKEN_PREFIX = "token_%s";
//2小时
Integer EXPIRE = 60;
}
4.配置登录的拦截器
配置类
package com.example.demo.config;
import com.example.demo.util.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* Demo class
*
* @author aslan
* @date 2017/12/12
*/
@Configuration
public class LoginInterceptor extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/test/**");
}
}
实现类:
package com.example.demo.util;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import com.example.demo.bean.RedisConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jca.context.SpringContextResourceAdapter;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Demo class
*
* @author aslan
* @date 2017/12/12
*/
public class MyInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("pre hander");
//判断该用户是否已登录,如果没有登录,跳转到登录界面
//获取token
Cookie[] cookies = httpServletRequest.getCookies();
String token =null;
for (Cookie cookie: cookies) {
if ("token".equals(cookie.getName())) {
token = cookie.getValue();
break;
}
}
//redisTemplate
ServletContext context = httpServletRequest.getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
StringRedisTemplate redisTemplate = ctx.getBean(StringRedisTemplate.class);
//从redis中检查该token是否存在
String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, token));
if (StringUtils.isEmpty(tokenValue)) {
System.out.println("【登录校验】Redis中查不到token");
return false;
}else {
System.out.println("get token " + tokenValue);
return true;
}
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println(" post hander");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("after ");
}
}
5.登录Controller
package com.example.demo.controller;
import com.example.demo.bean.RedisConstant;
import com.sun.deploy.net.HttpRequest;
import com.sun.deploy.net.HttpResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* Created by Administrator on 2017/12/11 0011.
*/
@RestController
@RequestMapping("/login")
public class LoginController {
@Autowired
private StringRedisTemplate redisTemplate;
@RequestMapping("/")
public String index(){
return "aha";
}
@RequestMapping(value = "/loginbypost", method = RequestMethod.POST)
public String loginByPost(@RequestParam(value = "name", required = true) String name,
@RequestParam(value = "pwd", required = true) String pwd,
HttpServletResponse response) {
//生成token
String token = UUID.randomUUID().toString();
// 设置token到cookie里面
Cookie cookie = new Cookie("token",token);
cookie.setPath("/");
cookie.setMaxAge(7200);
response.addCookie(cookie);
return null;
}
@RequestMapping(value = "/loginbyget", method = RequestMethod.GET)
public String loginByGet(@RequestParam(value = "name", required = true) String name,
@RequestParam(value = "pwd", required = true) String pwd,
HttpServletResponse response) {
//生成token
String token = UUID.randomUUID().toString();
Integer expire = RedisConstant.EXPIRE;
redisTemplate.opsForValue().set(String.format(RedisConstant.TOKEN_PREFIX, token), "didididi", expire, TimeUnit.SECONDS);
// 设置token到cookie里面
Cookie cookie = new Cookie("token",token);
cookie.setPath("/");
cookie.setMaxAge(120);
response.addCookie(cookie);
return "login success";
}
@RequestMapping(value = "/getit",method = RequestMethod.GET)
public String getit(HttpServletRequest request){
Cookie[] cookies = request.getCookies();
String token =null;
for (Cookie cookie: cookies) {
if ("token".equals(cookie.getName())) {
token = cookie.getValue();
break;
}
}
String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, token));
if (StringUtils.isEmpty(tokenValue)) {
System.out.println("【登录校验】Redis中查不到token");
}else {
System.out.println("get token " + token);
}
return null;
}
}
6.测试Controller
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Demo class
*
* @author aslan
* @date 2017/12/12
*/
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/getone")
public String getone(){
return "in 3 getone";
}
@RequestMapping("/gettwo")
public String gettwo(){
return "in 3 gettwo";
}
@RequestMapping("/getthree")
public String getthree(){
return "in 3 getthree";
}
}
7.测试方法
nginx做负载均衡