利用JWT做权限验证

实现Token的方式有很多,本篇介绍的是利用Json Web Token(JWT)生成的Token.JWT生成的Token有什么好处呢?

  • 安全性比较高,加上密匙加密而且支持多种算法。
  • 携带的信息是自定义的,而且可以做到验证token是否过期。
  • 验证信息可以由前端保存,后端不需要为保存token消耗内存。

本篇分3部分进行讲解。

  1. 什么是JWT
  2. JWT的代码实现,代码将JWT封装成两个工具类,可以直接调用。
  3. 总结

什么是JWT

JSON Web Token 简称JWT。
一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
JWT生成的token是这样的

eyJpc3MiOiJKb2huI.eyJpc3MiOiJ.Kb2huIFd1IEp

生成的token,是3段,用.连接。下面有解释。

头部

用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。
例如:

{
   "typ": "JWT",
  "alg": "HS256"
}

载荷

其实就是自定义的数据,一般存储用户Id,过期时间等信息。也就是JWT的核心所在,因为这些数据就是使后端知道此token是哪个用户已经登录的凭证。而且这些数据是存在token里面的,由前端携带,所以后端几乎不需要保存任何数据。
例如:

{
  "uid": "xxxxidid",  //用户id
  "exp": "12121212"  //过期时间
}

签名

签名其实就是:

  1. 头部和载荷各自base64加密后用.连接起来,然后就形成了xxx.xx的前两段token。
  2. 最后一段token的形成是,前两段加入一个密匙用HS256算法或者其他算法加密形成。
  3. 所以token3段的形成就是在签名处形成的。

JWT的原理参考文章

代码实现

  1. 看代码前一定要知道JWT是由头部、载荷与签名组成。
  2. 代码将JWT封装成两个工具类,可以直接调用。

需要下载的jar包

<dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.4.0</version>
</dependency>

JWT工具类

import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;

public class JWT {
	private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";

	private static final String EXP = "exp";

	private static final String PAYLOAD = "payload";

	//加密,传入一个对象和有效期
	public static <T> String sign(T object, long maxAge) {
		try {
			final JWTSigner signer = new JWTSigner(SECRET);
			final Map<String, Object> claims = new HashMap<String, Object>();
			ObjectMapper mapper = new ObjectMapper();
			String jsonString = mapper.writeValueAsString(object);
			claims.put(PAYLOAD, jsonString);
			claims.put(EXP, System.currentTimeMillis() + maxAge);
			return signer.sign(claims);
		} catch(Exception e) {
			return null;
		}
	}

	//解密,传入一个加密后的token字符串和解密后的类型
	public static<T> T unsign(String jwt, Class<T> classT) {
		final JWTVerifier verifier = new JWTVerifier(SECRET);
		try {
			final Map<String,Object> claims= verifier.verify(jwt);
			if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
				long exp = (Long)claims.get(EXP);
				long currentTimeMillis = System.currentTimeMillis();
				if (exp > currentTimeMillis) {
					String json = (String)claims.get(PAYLOAD);
					ObjectMapper objectMapper = new ObjectMapper();
					return objectMapper.readValue(json, classT);
				}
			}
			return null;
		} catch (Exception e) {
			return null;
		}
	}
}

WebConfigurer类

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.WebMvcConfigurationSupport;
import com.hc.interceptor.TokenInterceptor;


@Configuration
public class WebConfigurer extends WebMvcConfigurationSupport {


	@Autowired
	private TokenInterceptor tokenInterceptor;
	
	// 这个方法是用来配置静态资源的,比如html,js,css,等等
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
	}

	// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// addPathPatterns("/**") 表示拦截所有的请求,
		// excludePathPatterns("/login", "/register") 表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
		registry.addInterceptor(tokenInterceptor).addPathPatterns("/**").excludePathPatterns("/login/**","/Typhoon/**","/Nephogram/**","/Ocean/**","/Siteinfo/**","/Siteinfo/**", "/User/**");
		super.addInterceptors(registry);
	}
}

设置token拦截器

import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.hc.config.JWT;
import com.hc.pojo.User;
import com.hc.util.ResponseData;

@Component
public class TokenInterceptor implements HandlerInterceptor{

	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception arg3)
					throws Exception {
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response,
			Object handler, ModelAndView model) throws Exception {
	}

	//拦截每个请求
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
			Object handler) throws Exception {
		response.setCharacterEncoding("utf-8");
		String token =request.getHeader("Authorization");
		ResponseData responseData = ResponseData.ok();
		//token不存在
		if(null != token) {
			User user = JWT.unsign(token, User.class);
			if(null != user) {
				return true;
			}else{
				responseData = ResponseData.tokenOverdue();
				responseMessage(response, response.getWriter(), responseData);
				return false;
			}
		}
		else
		{
			responseData = ResponseData.forbidden();
			responseMessage(response, response.getWriter(), responseData);
			return false;
		}
	}

	//请求不通过,返回错误信息给客户端
	private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseData responseData) {
		response.setContentType("application/json; charset=utf-8");  
		String json = JSONObject.toJSONString(responseData);
		out.print(json);
		out.flush();
		out.close();
	}

}

调用业务逻辑

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.hc.config.JWT;
import com.hc.pojo.User;
import com.hc.service.UserService;
import com.hc.util.ResponseData;

@Controller
@RequestMapping(value = "/User", produces = MediaType.APPLICATION_JSON_VALUE)
@CrossOrigin(origins="*")
public class UserController {

	@Autowired
	private UserService userService;

	private static final Integer rolename = 1;//管理员权限

	/**
	 * 权限判断 
	 * */
	public boolean token(String token) {
		User user = JWT.unsign(token, User.class);
		if(user.getRole()==rolename) {
			return true;
		}else {
			return false;
		}

	}

	/**
	 * 用户添加
	 * */
	@RequestMapping("addUser")
	@ResponseBody
	public Object addUser(User user,@RequestHeader("Authorization") String token) {
		if(token(token)) {
			Integer num = userService.addUser(user);
			if(num > 0) {
				return  user.getId();
			}else {
				return ResponseData.serverInternalError();
			}
		}else {
			return ResponseData.unauthorized();
		}
	}

猜你喜欢

转载自blog.csdn.net/weixin_43923112/article/details/87070489
今日推荐