springboot——基于JWT的token认证 - Go语言中文社区

springboot——基于JWT的token认证


一.介绍

1、JSON Web Token,简称JWT,本质是一个token,是一种紧凑的URL安全方法,用于在网络通信的双方之间传递。

2、一般放在HTTP的headers 参数里面的authorization里面,值的前面加Bearer关键字和空格。

3、主要用于身份认证和信息交换

4、由三部分组成,用英文句点连接(.),例如:xxxxxx.yyyyyy.zzzzzz

——认证呢,有很多种,session 认证,basic auth 认证,OAuth认证,token认证等。这里只是介绍了其中基于JWT技术的token认证而已。用token认证,很好解决大型分布式横行扩展问题。

二、JWT的结构语法:https://blog.csdn.net/buyaoshuohua1/article/details/73739419/

三、模仿登录+过滤器(springboot demo)

(1)流程:

登录接口未做拦截创建token

非登录接口被过滤器拦截>>验证token是否存在,是否失效>>验证成功则返回,否则就返回

(2)实现:

1、添加依赖

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

2、TokenObject

package com.example.demo.common.bo;

import org.springframework.stereotype.Component;

@Component
public class TokenObject {
	/**客户端id*/
    private String clientId;
    /**base64加密*/
    private String base64Secret;
    /**用户名*/
    private String name;
    /**到期时间*/
    private long expiresSecond;
    /**管理员名称*/
    private String userName;
    /**管理员id*/
    private Integer aId;
    /**职能*/
    private String role;
    /**项目名称*/
    private String project;
	public String getClientId() {
		return clientId;
	}
	public void setClientId(String clientId) {
		this.clientId = clientId;
	}
	public String getBase64Secret() {
		return base64Secret;
	}
	public void setBase64Secret(String base64Secret) {
		this.base64Secret = base64Secret;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public long getExpiresSecond() {
		return expiresSecond;
	}
	public void setExpiresSecond(long expiresSecond) {
		this.expiresSecond = expiresSecond;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public Integer getaId() {
		return aId;
	}
	public void setaId(Integer aId) {
		this.aId = aId;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	public String getProject() {
		return project;
	}
	public void setProject(String project) {
		this.project = project;
	}
    

}

3、JwtHelper

package com.example.demo.common.utils;

import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.common.bo.TokenObject;

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.Base64Codec;

public class JwtHelper {
	private static Logger logger = LoggerFactory.getLogger(JwtHelper.class);

    /**
     * 校验Token
     * @param jwt
     * @param httpRequest
     * @return
     */
    public static int checkToken(String jwt, HttpServletRequest httpRequest){
        if (!StringUtils.isBlank(jwt)){
            if (jwt.split("\.").length==3) {
                logger.info("jwt:" + jwt);
                String[] split = jwt.split("\.");
                String content = split[1];//负荷
                String s = Base64Codec.BASE64URL.decodeToString(content);
                logger.info("s:" + s);
                String sign = split[2];//签名
                logger.info("sign:" + sign);
                JSONObject jsonObject1 = JSONObject.parseObject(s);

                long nowMillis = System.currentTimeMillis();
                Date now = new Date(nowMillis);
                long expiresSecond = (long) jsonObject1.get("expiresSecond");

                //判断是否过期
                if(now.getTime()>expiresSecond)
                     return 2;


                TokenObject o = (TokenObject) JSONObject.toJavaObject(jsonObject1, TokenObject.class);
//                 if (o!=null){
//                    String project = o.getProject();
//                   // if (!StaticInfo.PROJECT.equals(project))
//                        return 0;
//                }
                String jwtByStr = createJWTByObj(o);
                String s2 = jwtByStr.split("\.")[2];
                logger.info("s2:" + s2);
                if (sign.equals(s2)) {
                	logger.info("验证成功");
                    return 1;
                } else
                    return 0;
            }
        }
        return 0;
    }

    /**
     * 获取用户id
     * @param jwt
     * @return
     */
    public static int  getIdByJWT(String jwt){
        if (!StringUtils.isBlank(jwt)) {
            if (jwt.split("\.").length == 3) {
                logger.info("jwt:" + jwt);
                String[] split = jwt.split("\.");
                String content = split[1];
                String s = Base64Codec.BASE64URL.decodeToString(content);
                JSONObject jsonObject1 = JSONObject.parseObject(s);
                TokenObject o = (TokenObject) JSONObject.toJavaObject(jsonObject1, TokenObject.class);
                return o.getaId();
            }
        }
        return 0;
    }
    
    /**
     * 获取用户clinetId
     * @param jwt
     * @return
     */
    public static String  getClinetIdByJWT(String jwt){
        if (!StringUtils.isBlank(jwt)) {
            if (jwt.split("\.").length == 3) {
                logger.info("jwt:" + jwt);
                String[] split = jwt.split("\.");
                String content = split[1];
                String s = Base64Codec.BASE64URL.decodeToString(content);
                JSONObject jsonObject1 = JSONObject.parseObject(s);
                TokenObject o = (TokenObject) JSONObject.toJavaObject(jsonObject1, TokenObject.class);
                return o.getClientId();
            }
        }
        return "";
    }

    /**
     * 获取客户信息
     * @param request
     * @return
     * @throws CustomException
     */
    public static int getIdByRequest(HttpServletRequest request) {
        int i = 0;
        String auth = request.getHeader("Authorization");
        if ((auth != null) && (auth.length() > 6)) {
            String HeadStr = auth.substring(0, 5).toLowerCase();
            if (HeadStr.compareTo("basic") == 0) {
                auth = auth.substring(6, auth.length());
                i = JwtHelper.getIdByJWT(auth);
            }
        }
        if (i==0)
           // throw new CustomException(ResultEnum.PERMISSION_DENIED);
		return i;
		return i;
    }

    public static String createJWTByObj(TokenObject tokenObject) {
        Object jsonObject = JSONObject.toJSON(tokenObject);
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        //long nowMillis = System.currentTimeMillis();
       // Date now = new Date(nowMillis);

        //生成签名密钥
        byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(tokenObject.getBase64Secret());//服务器自己定义的秘钥
        SecretKeySpec signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setPayload(jsonObject.toString())
                .signWith(signatureAlgorithm, signingKey);

        //生成JWT
        return builder.compact();
    }

}

4、AuthUtil

public class AuthUtil {
	public static String getClinetIdByAuth(HttpServletRequest request) {
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		String auth = httpRequest.getHeader("Authorization");
		auth = auth.substring(7, auth.length());
		return JwtHelper.getClinetIdByJWT(auth);
	}

}

5、HTTPBasicAuthorizeAttribute

@Order(value = 1) 
@WebFilter(filterName = "colationFilter", urlPatterns = "/testtoken/*")
public class HTTPBasicAuthorizeAttribute implements Filter {

	private Logger logger = LoggerFactory.getLogger(HTTPBasicAuthorizeAttribute.class);

	@Override
	public void destroy() {
		logger.info("后台token过滤器,溜了溜了溜了溜了");
		// 可以日志管理添加
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		logger.info("后台token过滤器检测");
		// 1.检测当前是否需要重新登录
		// if(audience!=null){
		// if (audience.getClientId().equals(StaticInfo.SIGNOUT)){
		// toResponse((HttpServletResponse) response,1,(HttpServletRequest)
		// request);
		// return;
		// }
		// }
		// 2.检测请求同token信息
		ResultEnum resultStatusCode = checkHTTPBasicAuthorize(request);
		if (resultStatusCode.equals(ResultEnum.INVALID_SINGTIMEOUT)) {// 超时
			toResponse((HttpServletResponse) response, 2, (HttpServletRequest) request);
			return;
		} else if (resultStatusCode.equals(ResultEnum.INVALID_PERMISSION_DENIED)) {// 权限不够
			toResponse((HttpServletResponse) response, 0, (HttpServletRequest) request);
			return;
		}
		logger.info("后台token过滤器检测通过");
		chain.doFilter(request, response);
	}

	/**
	 * 响应
	 * 
	 * @param response
	 * @param i
	 *            类型
	 * @throws IOException
	 */
	private void toResponse(HttpServletResponse response, int i, HttpServletRequest request) throws IOException {
		HttpServletResponse httpResponse = response;
		httpResponse.setCharacterEncoding("UTF-8");
		httpResponse.setContentType("application/json; charset=utf-8");
		httpResponse.setHeader("Access-Control-Allow-Origin", "*");
		httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
		httpResponse.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,PATCH,PUT");
		httpResponse.setHeader("Access-Control-Max-Age", "3600");
		httpResponse.setHeader("Access-Control-Allow-Headers",
				"Origin,X-Requested-With,x-requested-with,X-Custom-Header," + "Content-Type,Accept,Authorization");
		String method = request.getMethod();
		if ("OPTIONS".equalsIgnoreCase(method)) {
			logger.info("OPTIONS请求");
			httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
		}

		ObjectMapper mapper = new ObjectMapper();
		PrintWriter writer = httpResponse.getWriter();
		// if (i==1)
		// writer.write(mapper.writeValueAsString(ResultEnum.RESTARTLOGIN));
		if (i == 2)
			writer.write(mapper.writeValueAsString(ResultEnum.INVALID_SINGTIMEOUT));
		else if (i == 0)
			writer.write(mapper.writeValueAsString(ResultEnum.INVALID_PERMISSION_DENIED));

		writer.close();

		if (writer != null)
			writer = null;
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		logger.info("后台token过滤器启动");
	}

	/**
	 * 检测请求同token信息
	 * 
	 * @param request
	 * @return
	 */
	private ResultEnum checkHTTPBasicAuthorize(ServletRequest request) {
		try {
			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("basic") == 0) {
					auth = auth.substring(6, auth.length());
					int i = JwtHelper.checkToken(auth, httpRequest);
					if (i == 1) {
						return ResultEnum.OK;
					} else if (i == 2) {
						return ResultEnum.INVALID_SINGTIMEOUT;
					} else if (i == 0) {
						return ResultEnum.INVALID_PERMISSION_DENIED;
					}
				}*/
				if (HeadStr.compareTo("bearer") == 0) {

					auth = auth.substring(7, auth.length());
					int i = JwtHelper.checkToken(auth, httpRequest);
					if (i == 1) {
						return ResultEnum.OK;
					} else if (i == 2) {
						return ResultEnum.INVALID_SINGTIMEOUT;
					} else if (i == 0) {
						return ResultEnum.INVALID_PERMISSION_DENIED;
					}
				}
			}
			return ResultEnum.INVALID_PERMISSION_DENIED;
		} catch (Exception ex) {
			return ResultEnum.INVALID_PERMISSION_DENIED;
		}

	}

}

6、LoginController

@Api(value = "LoginController")
@RequestMapping("/api")
@Controller
public class LoginController {

	@ApiOperation(value = "登录测试方法", notes = "登录测试方法")
	@RequestMapping(value = "/login", method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ResponseBody
	public ResultModel<String> login(@RequestBody String userName) {
		System.out.println("用户名:"+userName);
		// 1、业务逻辑
		// 2、返回token
		TokenObject token = new TokenObject();
		token.setBase64Secret("test");
		token.setClientId(userName);
		token.setExpiresSecond(new Date().getTime() + 5*60 * 1000);
		return ResultModel.success(JwtHelper.createJWTByObj(token));
	}

}

7、TestTokenController

@Api(value = "TestTokenController")
@RequestMapping("/testtoken")
@RestController
public class TestTokenController {

	@ApiOperation(value = "token测试方法", notes = "token测试方法")
	@RequestMapping(value = "/test", method = RequestMethod.POST)
	public ResultModel<String> test(String p,HttpServletRequest request) {
		return ResultModel.success(AuthUtil.getClinetIdByAuth(request));
	}

}

(3)效果:

登录:

用token访问业务接口:

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_42683700/article/details/81077039
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-07 22:23:58
  • 阅读 ( 910 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢