本次项目中使用了认证拦截器来拦截非登录的请求,本来想通过@WebFilter来实现,但是发现没起作用,后面有时间换用@WebFilter注解实现。
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Configuration
@Component
@WebFilter(urlPatterns = {"/merchant/*"}, filterName = "tokenAuthFilter",
initParams = {
@WebInitParam(name = "loginUI", value = "/merchant/login"),
@WebInitParam(name = "captchaImage", value = "/merchant/captchaImage"),
@WebInitParam(name = "encoding", value = "utf-8")
})
@Order(1)
public class TokenAuthFilter implements Filter {
private FilterConfig config;
@Autowired
private RedisService redisService;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse rep = (HttpServletResponse) response;
// 设置允许跨域的配置
// 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
rep.setHeader("Access-Control-Allow-Origin", "*");
// 允许的访问方法
rep.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS");
// Access-Control-Max-Age 用于 CORS 相关配置的缓存
rep.setHeader("Access-Control-Max-Age", "3600");
rep.setHeader("Access-Control-Allow-Headers", "token,Origin, X-Requested-With, Content-Type, Accept");
rep.setCharacterEncoding("UTF-8");
// 不带http://域名:端口的地址
String uri = req.getRequestURI();
if (uri.contains("/merchant/login") ||
uri.contains("/merchant/captchaImage") ) {
//如果是登录页,则放行调用登录方法
// 请求登录,放行
chain.doFilter(request, response);
} else {
//用头部进行校验是否用户登录,为了防止经常调用该接口,建议缓存
String token = getToken(req);
if (token != null && !"null".equals(token)) {
String userName = (String) redisService.get(MERCHANT_USER_LOGIN + token);
if (userName != null) {
if(uri.contains("/merchant/logout")) {
LoginContext.clearLoginUserName();
ServletUtils.renderString(rep, JSON.toJSONString(AjaxResult.error(HttpStatus.SUCCESS, "退出成功")));
return;
} else {
// 放入到ThreadLocal中
LoginContext.setLoginUserName(userName);
}
// 已经登录,放行进行业务请求
try {
chain.doFilter(req, rep);
} finally {
LoginContext.clearLoginUserName();
}
} else {
AjaxResult.error("操作错误");
return;
}
} else {
return;
}
}
}
@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
@Override
public void destroy() {
this.config = null;
}
/**
* 获取请求token
*
* @param request
* @return token
*/
private String getToken(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (StringUtils.isNotEmpty(token) && token.startsWith("Bearer ")) {
token = token.replace("Bearer ", "");
}
return token;
}
}
LoginContext实现
public class LoginContext {
private static final ThreadLocal<String> loginthreadLocal = new ThreadLocal<>();
public static String getLoginUserName() {
return loginthreadLocal.get();
}
public static void setLoginUserName(String userName) {
loginthreadLocal.set(userName);
}
public static void clearLoginUserName() {
loginthreadLocal.remove();
}
}