JWT生成JsonWebToken登录令牌并使用自定义过滤器验证(包含跨域设置)

#JWT生成JsonWebToken登录令牌并使用自定义过滤器验证(包含跨域设置)

使用jwt生成jsonwebtoken 并且在自定义过滤器中进行登陆验证实现步骤如下:
1、Maven环境下引入jjwt包。


	<!-- jwt -->
	<dependency>
		<groupId>io.jsonwebtoken</groupId>
		<artifactId>jjwt</artifactId>
		<version>0.6.0</version>
	</dependency>

2、创建配置文件webtoken.properties并设置JWT相关信息。


expiresSecond=15 
salt=ikingtech
name=faultapiuser

expiresSecond表示超时时间,单位“天”。
salt可以是一个base64位的签名,用以区别发行人。
name表示发行人名称。
3、创建实体类用以获取配置信息。


import org.springframework.stereotype.Component;
/**
 * 加载jwt配置文件类
 * @author hufx
 * @version 1.0
 * @date 2017年1月22日上午11:44:33
 */ 
@Component
public class WebToken { 

	private String salt;			//base64位签名
	
	private String name;			//发行人名称
	
	private int expiresSecond;		//保存时间
	
	public String getSalt() {
		return salt;
	}
	
	public void setSalt(String salt) {
		this.salt = salt;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public int getExpiresSecond() {
		return expiresSecond;
	}
	
	public void setExpiresSecond(int expiresSecond) {
		this.expiresSecond = expiresSecond;
	}
	
	@Override
	public String toString() {
		return "WebToken [salt=" + salt + ", name=" + name + ", expiresSecond=" + expiresSecond + "]";
	}

}

4、创建工具类生成及解析token值。


@SuppressWarnings("deprecation")
@Component
public class FaultUtil {
	private static Logger log = LoggerFactory.getLogger(FaultUtil.class);
	private static WebToken webToken = new WebToken();
	static {
		try {
			Resource resource = new ClassPathResource("/webtoken.properties");
			Properties Props = PropertiesLoaderUtils.loadProperties(resource);
			webToken.setExpiresSecond(Props.getProperty("expiresSecond") == null ? 6379
					: Integer.parseInt(Props.getProperty("expiresSecond")));
			webToken.setName(Props.getProperty("name"));
			webToken.setSalt(Props.getProperty("salt"));
		} catch (IOException e) {
			log.error("获取 WebTokenProps : " + e);
		}
	}
	/**
	 * @desc 生成一个token值
	 * @param key
	 * @param obj
	 * @return
	 */
	public static String getWebToken(String key, Object obj) {
		long nowMillis = System.currentTimeMillis();
		Date now = new Date(nowMillis);
		// 生成签名密钥
		byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(webToken.getSalt());
		Key signingKey = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
		// 添加构成JWT的参数
		JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT").claim(key, obj).setIssuer(webToken.getName())
				.signWith(SignatureAlgorithm.HS256, signingKey);
		// 添加Token过期时间
		long TTLMillis = webToken.getExpiresSecond() * 24 * 60 * 60 * 1000;
		if (TTLMillis >= 0) {
			long expMillis = nowMillis + TTLMillis;
			Date exp = new Date(expMillis);
			builder.setExpiration(exp).setNotBefore(now);
		}
		// 生成JWT
		return builder.compact();
	}
	/**
	 * @desc 解析token值
	 * @param jsonWebToken
	 * @param base64Security
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> parseWebToken(String jsonWebToken, String key) {
		try {
			Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(webToken.getSalt()))
					.parseClaimsJws(jsonWebToken).getBody();

			Map<String, Object> res = (Map<String, Object>) claims.get(key);
			return res;
		} catch (Exception ex) {
			log.error("解析token值:" + ex);
		}
		return null;
	}
	/**
	 * 获取webtoken的失效时间
	 * 
	 * @param jsonWebToken
	 * @param key
	 * @return
	 * @date 2017年7月10日 上午11:52:52
	 */
	public static Long getWebTokenTime(String jsonWebToken, String key) {
		try {
			Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(webToken.getSalt()))
					.parseClaimsJws(jsonWebToken).getBody();
			return claims.getExpiration().getTime();
		} catch (Exception ex) {
			log.error("解析token值:" + ex);
		}
		return null;
	}
	/**
	 * 获取当前登录的用户对象
	 * HttpUserInfoRes
	 * @author hufx
	 * @date 2017年8月15日上午11:53:35
	 */
	 public static HttpUserInfoRes getUserByWebToken(HttpServletRequest request) {
		 try {
			String jsonWebToken = request.getHeader("token");
			 if (jsonWebToken == null) {
				 return null;
			 }
			 Map<String, Object> tUserMap = (Map<String, Object>)parseWebToken(jsonWebToken, "tUser");
			 if (tUserMap == null) {
				 return null;
			 }
			 //获取当前登录用户时可返回此对象
			 //HttpUserInfoRes user = new HttpUserInfoRes();
			 //user.setfId((String) tUserMap.get("fId"));
			 //user.setfLoginName((String) tUserMap.get("fLoginName"));
			 //user.setfEmployeeId((String) tUserMap.get("fEmployeeId"));
			 //user.setfRegisterTime(new Date((long)tUserMap.get("fRegisterTime")));
			 //user.setfLastLoginIp((String) tUserMap.get("fLastLoginIp"));
			 //user.setfLastLoginTime(new Date((long)tUserMap.get("fLastLoginTime")));
			 //user.setfLoginCount((Integer) tUserMap.get("fLoginCount"));
			 //user.setfUserName((String) tUserMap.get("fUserName"));
			 //return user;
		} catch (Exception e) {
			return null;
		}
	 }
}

5、登录成功之后生成并返回token值。
登录校验成功之后生成token值并返回此值,之后每次前端将此token值放进请求头中即可。tUser表示用户对象,可根据实际需要添加。


//			HttpUserInfoRes tUserRes = new HttpUserInfoRes(); // 封装返回对象
//			tUserRes.setfId(tUser.getfId());
//			tUserRes.setfLoginName(tUser.getfLoginName());
//			tUserRes.setfEmployeeId(tUser.getfEmployeeId());
//			tUserRes.setfRegisterTime(tUser.getfRegisterTime());
//			tUserRes.setfLastLoginIp(tUser.getfLastLoginIp());
//			tUserRes.setfLoginCount(tUser.getfLoginCount());
//			tUserRes.setfLastLoginTime(tUser.getfLastLoginTime());
//			tUserRes.setfUserName(tEmployee.getfUserName());
//			String accessToken = FaultUtil.getWebToken("tUser", tUserRes); // 登录成功,生成webtoken
//			tUserRes.setWebtoken(accessToken);

HttpUserInfoRes继承tUser对象并包含属性:


	private String webtoken;// token
	private String fUserName;// 用户名称

tUser对象属性:


private String fId;// 账号id

private String fLoginName;// 账号

private String fPassword;// 密码

private String fEmployeeId;// 使用人id

private Date fRegisterTime;// 注册时间

private String fLastLoginIp;// 上次登录ip

private Date fLastLoginTime;// 上次登陆时间

private Integer fLoginCount;// 登陆次数

private Boolean fIsEnable;// 是否可用

private Boolean fIsDelete;// 是否删除

6、添加过滤器进行token验证。
添加如下配置:


import java.util.ArrayList;
import java.util.List;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.iking.fault.filter.HTTPBearerAuthorizeAttribute;

@Configuration
public class FilterConfig {
	
	@Bean
	public FilterRegistrationBean jwtFilterRegistrationBean(){
		//拦截器
		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
		//自定义拦截类
		HTTPBearerAuthorizeAttribute httpBearerFilter = new HTTPBearerAuthorizeAttribute();
		registrationBean.setFilter(httpBearerFilter);
		List<String> urlPatterns = new ArrayList<String>();
		urlPatterns.add("/*");
	    registrationBean.setUrlPatterns(urlPatterns);
	    return registrationBean;
	}
}

创建自定义过滤器类并进行过滤配置(包含跨域设置):


import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.HttpStatus;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iking.fault.model.Msg;
import com.iking.fault.util.FaultUtil;

/**
 * 请求过滤类
 * 
 * @author hufx
 * @version 1.0
 * @date 2017年1月22日下午3:33:01
 * 
 *       <br/>
 *       备注:从请求header中获取token时的key值约定为 “webtoken”,类型为String
 */
public class HTTPBearerAuthorizeAttribute implements Filter {

	private static List<String> releaseList = new ArrayList<String>(); 	// 放行接口列表

	static {
		releaseList.add("/user/login"); 								// pc登录
		releaseList.add("/home");										//主页
		releaseList.add("/qlOutfieldMonitoring/export");				//飞行状态更新导出
		releaseList.add("/pageoffice/");								//pageoffice/
		releaseList.add("/faultfile/");									//文件
	}

	private static List<String> accessTokenKeyList = new ArrayList<String>();// webtokenkey列表

	static {
		accessTokenKeyList.add("tUser"); // pc
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws JsonProcessingException, IOException {
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;
		httpResponse.setCharacterEncoding("UTF-8");
		httpResponse.setContentType("application/json; charset=utf-8");
		httpResponse.setHeader("Access-Control-Allow-Origin", "*"); 
		if("OPTIONS".equals(httpRequest.getMethod())) {
			httpResponse.setStatus(HttpStatus.SC_NO_CONTENT); //HttpStatus.SC_NO_CONTENT = 204
			httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
			httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with, Token");  
			httpResponse.setHeader("Access-Control-Allow-Methods", "OPTIONS,GET,POST,DELETE,PUT"); 
		}
		ObjectMapper mapper = new ObjectMapper();
		String webtoken = httpRequest.getHeader("token"); // 从请求header中拿出webtoken
		String thisUrl = httpRequest.getRequestURL().toString();
		try {
			//登录和测试接口放行,其余接口全部监听
//			if (webtoken == null) { // 测试时 webtoken校验放行 swagger-ui
//				chain.doFilter(request, response);
//				return;
//			}

			for (String url : HTTPBearerAuthorizeAttribute.releaseList) { // 验证放行接口
				if (thisUrl.indexOf(url) > 0) {
					chain.doFilter(request, response);
					return;
				}
			}

			if (webtoken != null && webtoken.length() > 7) { // 校验token值
				for (String key : accessTokenKeyList) {
					Map<String, Object> tUserMap = (Map<String, Object>) FaultUtil.parseWebToken(webtoken, key);
					if (tUserMap != null) {
						chain.doFilter(request, response);
						return;
					}
				}
			}
		} catch (Exception e) {
		}
		//Msg msg = new Msg();
		//msg.setSuccess(false);
		//msg.setMsg("未登录或登录超时!");
		//httpResponse.getWriter().write(mapper.writeValueAsString(msg));
		return;
	}

	@Override
	public void destroy() {
	}
}

7、前端设置。
前端页面登录成功后拿到token值,首先要将其存在本地,localStorage或者sessionStorage皆可。然后添加前端的拦截器,在每次请求之前将此token值放入request对象的header中即可(此处以Vue-Axios为例):


// 添加webtoken
Axios.interceptors.request.use(function (config) {
  // 在请求发出之前进行一些操作
  if (localStorage.webtoken) {
    config.headers = {
      'token': localStorage.webtoken
    }
  }
  return config
}, function (err) {
  // Do something with request error
})

至此,一个跨域的JWT登录验证功能完成了。如有疑问烦请@笔者:Q:980420579 Q群:697819474

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值