[转] Spring Boot实战之Filter实现使用JWT进行接口认证
【From】 http://blog.csdn.net/sun_t89/article/details/51923017
Spring Boot实战之Filter实现使用JWT进行接口认证
jwt(json web token)
用户发送按照约定,向服务端发送 Header、Payload 和 Signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api
jwt使用流程
本文示例接上面几篇文章中的代码进行编写,请阅读本文的同时可以参考前面几篇文章
1、添加依赖库jjwt,本文中构造jwt及解析jwt都使用了jjwt库
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.6.0</version>
- </dependency>
2、添加登录获取token时,所需要的认证信息类LoginPara.java
- package com.xiaofangtech.sunt.jwt;
- public class LoginPara {
- private String clientId;
- private String userName;
- private String password;
- private String captchaCode;
- private String captchaValue;
- public String getClientId() {
- return clientId;
- }
- public void setClientId(String clientId) {
- this.clientId = clientId;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public String getCaptchaCode() {
- return captchaCode;
- }
- public void setCaptchaCode(String captchaCode) {
- this.captchaCode = captchaCode;
- }
- public String getCaptchaValue() {
- return captchaValue;
- }
- public void setCaptchaValue(String captchaValue) {
- this.captchaValue = captchaValue;
- }
- }
3、添加构造jwt及解析jwt的帮助类JwtHelper.java
- package com.xiaofangtech.sunt.jwt;
- import java.security.Key;
- import java.util.Date;
- import javax.crypto.spec.SecretKeySpec;
- import javax.xml.bind.DatatypeConverter;
- import io.jsonwebtoken.Claims;
- import io.jsonwebtoken.JwtBuilder;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.SignatureAlgorithm;
- public class JwtHelper {
- public static Claims parseJWT(String jsonWebToken, String base64Security){
- try
- {
- Claims claims = Jwts.parser()
- .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
- .parseClaimsJws(jsonWebToken).getBody();
- return claims;
- }
- catch(Exception ex)
- {
- return null;
- }
- }
- public static String createJWT(String name, String userId, String role,
- String audience, String issuer, long TTLMillis, String base64Security)
- {
- SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
- long nowMillis = System.currentTimeMillis();
- Date now = new Date(nowMillis);
- //生成签名密钥
- byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
- Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
- //添加构成JWT的参数
- JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
- .claim("role", role)
- .claim("unique_name", name)
- .claim("userid", userId)
- .setIssuer(issuer)
- .setAudience(audience)
- .signWith(signatureAlgorithm, signingKey);
- //添加Token过期时间
- if (TTLMillis >= 0) {
- long expMillis = nowMillis + TTLMillis;
- Date exp = new Date(expMillis);
- builder.setExpiration(exp).setNotBefore(now);
- }
- //生成JWT
- return builder.compact();
- }
- }
4、添加token返回结果类AccessToken.java
- package com.xiaofangtech.sunt.jwt;
- public class AccessToken {
- private String access_token;
- private String token_type;
- private long expires_in;
- public String getAccess_token() {
- return access_token;
- }
- public void setAccess_token(String access_token) {
- this.access_token = access_token;
- }
- public String getToken_type() {
- return token_type;
- }
- public void setToken_type(String token_type) {
- this.token_type = token_type;
- }
- public long getExpires_in() {
- return expires_in;
- }
- public void setExpires_in(long expires_in) {
- this.expires_in = expires_in;
- }
- }
5、添加获取token的接口,通过传入用户认证信息(用户名、密码)进行认证获取
- package com.xiaofangtech.sunt.jwt;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import com.xiaofangtech.sunt.bean.UserInfo;
- import com.xiaofangtech.sunt.repository.UserInfoRepository;
- import com.xiaofangtech.sunt.utils.MyUtils;
- import com.xiaofangtech.sunt.utils.ResultMsg;
- import com.xiaofangtech.sunt.utils.ResultStatusCode;
- @RestController
- public class JsonWebToken {
- @Autowired
- private UserInfoRepository userRepositoy;
- @Autowired
- private Audience audienceEntity;
- @RequestMapping("oauth/token")
- public Object getAccessToken(@RequestBody LoginPara loginPara)
- {
- ResultMsg resultMsg;
- try
- {
- if(loginPara.getClientId() == null
- || (loginPara.getClientId().compareTo(audienceEntity.getClientId()) != 0))
- {
- resultMsg = new ResultMsg(ResultStatusCode.INVALID_CLIENTID.getErrcode(),
- ResultStatusCode.INVALID_CLIENTID.getErrmsg(), null);
- return resultMsg;
- }
- //验证码校验在后面章节添加
- //验证用户名密码
- UserInfo user = userRepositoy.findUserInfoByName(loginPara.getUserName());
- if (user == null)
- {
- resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(),
- ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null);
- return resultMsg;
- }
- else
- {
- String md5Password = MyUtils.getMD5(loginPara.getPassword()+user.getSalt());
- if (md5Password.compareTo(user.getPassword()) != 0)
- {
- resultMsg = new ResultMsg(ResultStatusCode.INVALID_PASSWORD.getErrcode(),
- ResultStatusCode.INVALID_PASSWORD.getErrmsg(), null);
- return resultMsg;
- }
- }
- //拼装accessToken
- String accessToken = JwtHelper.createJWT(loginPara.getUserName(), String.valueOf(user.getName()),
- user.getRole(), audienceEntity.getClientId(), audienceEntity.getName(),
- audienceEntity.getExpiresSecond() * 1000, audienceEntity.getBase64Secret());
- //返回accessToken
- AccessToken accessTokenEntity = new AccessToken();
- accessTokenEntity.setAccess_token(accessToken);
- accessTokenEntity.setExpires_in(audienceEntity.getExpiresSecond());
- accessTokenEntity.setToken_type("bearer");
- resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(),
- ResultStatusCode.OK.getErrmsg(), accessTokenEntity);
- return resultMsg;
- }
- catch(Exception ex)
- {
- resultMsg = new ResultMsg(ResultStatusCode.SYSTEM_ERR.getErrcode(),
- ResultStatusCode.SYSTEM_ERR.getErrmsg(), null);
- return resultMsg;
- }
- }
- }
6、添加使用jwt认证的filter
- package com.xiaofangtech.sunt.filter;
- import java.io.IOException;
- 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.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.context.support.SpringBeanAutowiringSupport;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.xiaofangtech.sunt.jwt.Audience;
- import com.xiaofangtech.sunt.jwt.JwtHelper;
- import com.xiaofangtech.sunt.utils.ResultMsg;
- import com.xiaofangtech.sunt.utils.ResultStatusCode;
- public class HTTPBearerAuthorizeAttribute implements Filter{
- @Autowired
- private Audience audienceEntity;
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- // TODO Auto-generated method stub
- SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
- filterConfig.getServletContext());
- }
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
- // TODO Auto-generated method stub
- ResultMsg resultMsg;
- HttpServletRequest httpRequest = (HttpServletRequest)request;
- String auth = httpRequest.getHeader("Authorization");
- if ((auth != null) && (auth.length() > 7))
- {
- String HeadStr = auth.substring(0, 6).toLowerCase();
- if (HeadStr.compareTo("bearer") == 0)
- {
- auth = auth.substring(7, auth.length());
- if (JwtHelper.parseJWT(auth, audienceEntity.getBase64Secret()) != null)
- {
- chain.doFilter(request, response);
- return;
- }
- }
- }
- HttpServletResponse httpResponse = (HttpServletResponse) response;
- httpResponse.setCharacterEncoding("UTF-8");
- httpResponse.setContentType("application/json; charset=utf-8");
- httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- ObjectMapper mapper = new ObjectMapper();
- resultMsg = new ResultMsg(ResultStatusCode.INVALID_TOKEN.getErrcode(), ResultStatusCode.INVALID_TOKEN.getErrmsg(), null);
- httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg));
- return;
- }
- @Override
- public void destroy() {
- // TODO Auto-generated method stub
- }
- }
7、在入口处注册filter
- package com.xiaofangtech.sunt;
- import java.util.ArrayList;
- import java.util.List;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.context.embedded.FilterRegistrationBean;
- import org.springframework.boot.context.properties.EnableConfigurationProperties;
- import org.springframework.context.annotation.Bean;
- import com.xiaofangtech.sunt.filter.HTTPBasicAuthorizeAttribute;
- import com.xiaofangtech.sunt.filter.HTTPBearerAuthorizeAttribute;
- import com.xiaofangtech.sunt.jwt.Audience;
- @SpringBootApplication
- @EnableConfigurationProperties(Audience.class)
- public class SpringRestApplication {
- public static void main(String[] args) {
- SpringApplication.run(SpringRestApplication.class, args);
- }
- @Bean
- public FilterRegistrationBean basicFilterRegistrationBean() {
- FilterRegistrationBean registrationBean = new FilterRegistrationBean();
- HTTPBasicAuthorizeAttribute httpBasicFilter = new HTTPBasicAuthorizeAttribute();
- registrationBean.setFilter(httpBasicFilter);
- List<String> urlPatterns = new ArrayList<String>();
- urlPatterns.add("/user/getuser");
- registrationBean.setUrlPatterns(urlPatterns);
- return registrationBean;
- }
- @Bean
- public FilterRegistrationBean jwtFilterRegistrationBean(){
- FilterRegistrationBean registrationBean = new FilterRegistrationBean();
- HTTPBearerAuthorizeAttribute httpBearerFilter = new HTTPBearerAuthorizeAttribute();
- registrationBean.setFilter(httpBearerFilter);
- List<String> urlPatterns = new ArrayList<String>();
- urlPatterns.add("/user/getusers");
- registrationBean.setUrlPatterns(urlPatterns);
- return registrationBean;
- }
- }
8、添加获取md5的方法类MyUtils
- package com.xiaofangtech.sunt.utils;
- import java.security.MessageDigest;
- public class MyUtils {
- public static String getMD5(String inStr) {
- MessageDigest md5 = null;
- try {
- md5 = MessageDigest.getInstance("MD5");
- } catch (Exception e) {
- e.printStackTrace();
- return "";
- }
- char[] charArray = inStr.toCharArray();
- byte[] byteArray = new byte[charArray.length];
- for (int i = 0; i < charArray.length; i++)
- byteArray[i] = (byte) charArray[i];
- byte[] md5Bytes = md5.digest(byteArray);
- StringBuffer hexValue = new StringBuffer();
- for (int i = 0; i < md5Bytes.length; i++) {
- int val = ((int) md5Bytes[i]) & 0xff;
- if (val < 16)
- hexValue.append("0");
- hexValue.append(Integer.toHexString(val));
- }
- return hexValue.toString();
- }
- }
9、在返回信息类中补充添加错误码
- INVALID_CLIENTID(30003, "Invalid clientid"),
- INVALID_PASSWORD(30004, "User name or password is incorrect"),
- INVALID_CAPTCHA(30005, "Invalid captcha or captcha overdue"),
- INVALID_TOKEN(30006, "Invalid token");
10、代码中涉及的Audience类,在上一篇文章中定义,本文不再重复说明
11、代码整体结构
12、测试
1) 获取token,传入用户认证信息
认证通过返回token信息
2) 使用上面获取的token进行接口调用
未使用token,获取token错误,或者token过期时
使用正确的token时
[转] Spring Boot实战之Filter实现使用JWT进行接口认证的更多相关文章
- 《spring boot 实战》读书笔记
前言:虽然已经用spring boot开发过一套系统,但是之前都是拿来主义,没有系统的,全面的了解过这套框架.现在通过学习<spring boot实战>这本书,希望温故知新.顺便实现自己的 ...
- spring boot实战(第一篇)第一个案例
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] spring boot实战(第一篇)第一个案例 前言 写在前面的话 一直想将spring boot相关内容写成一个系列的 ...
- 《Spring Boot实战》笔记(目录)
目录 目 录第一部分 点睛Spring 4.x第1 章 Spring 基础 .............................................................. ...
- 《Spring Boot 实战纪实》之过滤器
导航 什么是过滤器 Spring的过滤器 Filter定义 过滤的对象 典型应用 过滤器的使用 Filter生命周期 过滤器链 自定义敏感词过滤器 新增自定义过滤器 添加 @WebFilter注解 添 ...
- spring boot实战(第十三篇)自动配置原理分析
前言 spring Boot中引入了自动配置,让开发者利用起来更加的简便.快捷,本篇讲利用RabbitMQ的自动配置为例讲分析下Spring Boot中的自动配置原理. 在上一篇末尾讲述了Spring ...
- spring boot实战(第十二篇)整合RabbitMQ
前言 最近几篇文章将围绕消息中间件RabbitMQ展开,对于RabbitMQ基本概念这里不阐述,主要讲解RabbitMQ的基本用法.Java客户端API介绍.spring Boot与RabbitMQ整 ...
- Spring Boot实战系列-----------邮件发送
快速导航 添加Maven依赖 配置文件增加邮箱相关配置 Service.Test项目代码构建 五种邮件发送类型讲解 文本邮件 html邮件 附件邮件 html内嵌图片邮件 模板邮件 问题汇总 添加ma ...
- Spring Boot 实战与原理分析视频课程
Spring Boot 实战与原理分析视频课程 链接:https://pan.baidu.com/share/init?surl=PeykcoeqZtd1d9lN9V_F-A 提取码: 关注公众号[G ...
- 9.Spring Boot实战之配置使用Logback进行日志记录
转自:https://blog.csdn.net/meiliangdeng1990/article/details/54300227 Spring Boot实战之配置使用Logback进行日志记录 在 ...
随机推荐
- Luogu 4284 [SHOI2014]概率充电器
BZOJ 3566 树形$dp$ + 概率期望. 每一个点的贡献都是$1$,在本题中期望就等于概率. 发现每一个点要通电会在下面三件事中至少发生一件: 1.它自己通电了. 2.它的父亲给它通电了. 3 ...
- Mysql处理海量数据时的一些优化查询速度方法(转)
最近一段时间由于工作需要,开始关注针对Mysql数据库的select查询语句的相关优化方法. 由于在参与的实际项目中发现当mysql表的数据量达到百万级时,普通SQL查询效率呈直线下降,而且如果whe ...
- Django框架 之 form组件
Django框架 之 form组件 浏览目录 Form介绍 普通的登录 使用form组件 Form详情 常用字段 校验 进阶 使用Django Form流程 一.Form介绍 我们之前在HTML页面中 ...
- 现代C++学习笔记之一入门篇:智能指针(C++ 11)
原始指针:通过new建立的*指针 智能指针:通过智能指针关键字(unique_ptr, shared_ptr ,weak_ptr)建立的指针 在现代 C++ 编程中,标准库包含智能指针,该指针用于确保 ...
- HttpUploader7-授权码配置
1.1. 七牛云存储 配置方式: 1.配置授权码 2.配置云存储 3.配置空间名称 4.配置上传地址 1.2. 阿里云存储 配置方式: 1.填写授权码 2.配置云存储为阿里云 ...
- 20169219 NMap+Wireshark实验报告
Tcpdump介绍 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中 ...
- MYSQL常用日期操作
mysql查询今天.昨天.7天.近30天.本月.上一月 数据 今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 SELECT ...
- APUE(3)---文件I/O (1)
一.引言 UNIX系统中的大多数文件对I/O只需用到5个函数:open/read/write/lseek和close,这些函数都是不带缓冲I/O(Unbuffered I/O).只要涉及到多个进程间共 ...
- Javascript脚本 : eval()函数
Javascript 中 eval(X)函数 是将参数 当做语句来执行 var number1='1+2'; alert(number1); 输出为 '12': var number2=eval('1 ...
- 201621123012 《Java程序设计》第1周学习总结
1. 本章学习总结 学习了java的理论知识和它与C语言的差别,什么是JVM,区分JRE与JDK并学习JAVA环境的安装.熟悉控制台下的常用命令,java函数的编写.熟练使用编写JAVA所需要的工具( ...