SpringBoot中如何使用jwt来保护接口数据
大神们:这是我在实际工作中实际使用的,写下来与君分享,没有多漂亮的排版,没有多牛逼的技术,但是都是实在实能够解决问题的。如果你有更好的方法,还请多多指教,共同进步。如果喜欢这类的文章,关注我哈。也可以去我的博客看(vsalw.com)----vsalw
![SpringBoot中如何防止接口数据泄露](http://p2.ttnews.xyz/loading.gif)
在使用springboot能够很方便的写接口,但是这些接口都是暴漏出来的,没有安全验证,任何人都可以调用显然这是不合理的。如果加个注册登录模块,只有登陆的用户才能调用,那么当你这个服务在N多节点部署时候,session共享又要解决,增加额外的开销。个人项目中使用的是jwt这个技术,简单说就是当你登陆成功后服务器会给你一个令牌,你拿着这个令牌去访问每个接口,服务器会对你的令牌进行鉴权,服务器能够知道你是谁,是否有权限。当在多个节点部署时候,每台服务器都是可以解析的。如果你有更好的解决方案,还请多多指教。下面说下我是怎么做的。本文是在一个springboot的Web项目基础上的。
思路:1.引入jwt的jar包 2.配置一个拦截器 并定义拦截路径 3.注册这个拦截器
注意:在拦截器里面拦截到请求后,进行令牌鉴权。比如查看用户角色,用户登陆时间,令牌是否过期等。在决定是否放行。
第一步:在springboot的web项目基础上添加jwt的jar包
第二步:配置一个拦截器,并定义拦截路径和规则,注意:secretkey是加解密的密钥、实际使用中替换成你自己的。
完整代码如下:
public class Filterdemo implements Filter {
private static Set<String> path = new HashSet<String>();
// 不拦截的路径
static {
path.add("/");
path.add("/favicon.ico");
path.add("/open");
path.add("/getcode");
path.add("/error");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("1.自定义过滤器初始化------");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String url = request.getRequestURI();
System.out.println("过滤器启动,---请求地址:" + url);
// 获取header
final String authHeader = request.getHeader("authorization");
//检查请求接口路径是否在允许的set内
if (path.contains(url)) {
filterChain.doFilter(request, response);
} else {
// 检查 authorization,并检查是否以 "Bearer "开头,注意有一个空格
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
throw new ServletException("认证信息为空或者认证信息不正确");
}
// 截取字符串,截取token
final String token = authHeader.substring(7);
try {
// 解密token
final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();
//把token放request,此处应根据自己实际业务进行
request.setAttribute("claims", claims);
} catch (final SignatureException e) {
throw new ServletException("Invalid token");
}
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
System.out.println("自定义过滤器销毁");
}
这里是拦截到请求的处理,实际上在用户登陆后就应该给用户颁发令牌,代码如下:
@RequestMapping("/login")
@ResponseBody
public String login(String userName, String passwd) {
//此处仅判断不为空就认为是合法用户,登陆成功
if (userName != null && passwd != null) {
// 生成jwt token返回给前台
String jwtToken = Jwts.builder()
//该JWT所面向的用户,是否使用是可选的;
.setSubject(userName)
//自己希望存储的数据,比如角色,可以放多个
.claim("roles", "member")
.claim("menu", "xxx")
//颁发时间
.setIssuedAt(new Date())
//加密算法和秘钥
.signWith(SignatureAlgorithm.HS256, "secretkey").compact();
return jwtToken;
} else {
System.out.println("用户名或密码为空");
}
return "hello";
}
第三步:注册这个拦截器,注册到系统里
@Configuration
public class filterConfig {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
//设定我们写的拦截器对象
filterRegistrationBean.setFilter(new Filterdemo());
//设定拦截路径
filterRegistrationBean.addUrlPatterns("/**");
//设置启动顺序,多个拦截器时候使用
filterRegistrationBean.setOrder(2);
return filterRegistrationBean;
}
}
閱讀更多 程序猿老王 的文章