需求:出于对接口的安全性的考虑,调用接口需要前端携带token值,以验证用户的合法性,如果用户合法,则允许用户调用接口,反之则禁止用户随意调用接口。
前提条件:这里的token值,是由用户登录时产生的随机码,当用户登录时,我们把生成token值和用户的信息,以key-value的形式存入redis,这样当前端调后端接口的时候,在请求头带上这个token值,我们就可以在后端写个拦截器,来校验用户的合法性了。
下面上代码:
只需要写红色框框中的两个类即可:
import com.pactera.config.intercepors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author xiwen
* @date 2020年6月1日
*/
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
/**
* 这个方法是用来配置静态资源的,比如html,js,css,等等
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns("/**") //表示拦截所有的请求,
// excludePathPatterns("/login", "/register") //表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
//(/**)==拦截所有请求
registry.addInterceptor(loginInterceptor).addPathPatterns("/**")
.excludePathPatterns("/pbms/sso/login", "/register")
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
//较新Spring Boot的版本中这里可以直接去掉,否则会报错
WebMvcConfigurer.super.addInterceptors(registry);
}
}
WebConfigurer :这个类中放开了swagger的访问,方便前后端联调
import com.sun.istack.Nullable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author xiwen
* @date 2020年6月1日
*/
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 这个方法是在访问接口之前执行的,我们只需要在这里写验证登陆状态的业务逻辑,就可以在用户调用指定接口之前验证登陆状态了
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String user = "";
try {
String token = request.getHeader("X-Token");
if (token == null) {
token = "";
}
user = redisTemplate.opsForValue().get(token);
} catch (Exception e) {
log.error("拦截器异常!" + e);
e.printStackTrace();
}
log.info("拦截状态===" + (user != null));
log.info("拦截请求===" + request.getRequestURI());
return user != null;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) {
}
}
LoginInterceptor:这个类是你自定义的拦截器,在preHandle()方法中你可以自定义拦截的条件,达到你所要拦截的目的。返回值是个布尔值,true表示不拦截,false表示拦截。