Java安全验证之jwt(json web token)

http://blog.csdn.net/u012017645/article/details/53585872


jwt token安全验证流程:用户发起登录请求,服务端创建一个加密后的jwt信息,作为token返回值,在后续请求中jwt信息作为请求头,服务端正确解密后可获取到存储的用户信息,表示验证通过;解密失败说明token无效或者已过期。

jwt token的组成:header.poyload.sign

  • header:头部,主要包括参数的类型--JWT,加密算法---RS512,头部由json字符串用base64编码生成;
  • poload:载荷,存放需要保存的一些用户信息,主要包括主题、签发者、接受者、到期时间等,载荷也由json字符串用base64编码生成,不能存放敏感数据;
  • sign:签名,防止恶意篡改数据。

依赖:

		<!-- 使用JWT在用户和服务器之间传递安全可靠的信息 -->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.6.0</version>
		</dependency>

jwt加解密的工具类:

package cn.lsh.util;

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;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;




import cn.lsh.entity.User;
import cn.lsh.vo.security.Audience;
import cn.lsh.vo.security.LoginParamter;

public class JwtUtils {
	private static final Logger LOGGER=LoggerFactory.getLogger(JwtUtils.class);
	
	private JwtUtils(){
		
	}

	/*
	 * 验证jwt是否合法,即解密
	 */
	public static Claims parseJWT(String jsonWebToken,String base64Security){
		try {
			return Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
					.parseClaimsJws(jsonWebToken)
					.getBody();		
		} catch (Exception e) {
			// TODO: handle exception
			LOGGER.error("exception message is: {}", ExceptionUtils.getStackTrace(e));
			return null;
		}
	}
	
	/*
	 * 创建jwt,即加密
	 */
	public static String createJWT(LoginParamter loginParamter,User user,Audience audience){
		long ttlmillis=audience.getExpiresSecond()*1000;
		String base64Security=audience.getBase64Secret();
		Date now=new Date(System.currentTimeMillis());
        
		//生成签名密钥
		byte[] apiKeySecretBytes=DatatypeConverter.parseBase64Binary(base64Security);
		Key signingKey=new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
		
		//添加构成JWT的参数		
		JwtBuilder builder=Jwts.builder().setHeaderParam("typ", "JWT")//typ表示token的类型
				.claim("role", user.getRole())// 自定义属性
				.claim("unique_name", loginParamter.getUserName())
				.claim("userid", user.getName())
				.setIssuer(audience.getName())// 签发者
				.setAudience(audience.getClientId())//接受者
				.signWith(SignatureAlgorithm.HS256, signingKey);// 签名算法以及密匙
		
        //添加Token过期时间
		if(ttlmillis>=0){
			Date exp=new Date(System.currentTimeMillis()+ttlmillis);
			builder.setExpiration(exp)// 过期时间
			.setNotBefore(now);// 失效时间
		}
		
		//生成JWT
		return builder.compact();
	}
	
	public static void main(String[] args) {
		Claims c=parseJWT("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoi566h55CG5ZGYIiwidW5pcXVlX25hbWUiOiJsaXVzaGlodWEiLCJ1c2VyaWQiOiJsaXVzaGlodWEiLCJpc3MiOiJsaXVzaGlodWEiLCJhdWQiOiIwOThmNmJjZDQ2MjFkMzczY2FkZTRlODMyNjI3YjRmNiIsImV4cCI6MTUwMjM1OTQ1NSwibmJmIjoxNTAyMzUyMjU0fQ.OeDN4deNUlDiUmwROjxw5_xrurJt46b1RZ0K5yNKH88", 
				"MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=");
		System.out.println(c);
	}
}

audience包含token的一些信息:

package cn.lsh.vo.security;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import lombok.Data;

@Data
//绑定属性的配置信息到该bean中,配置信息前缀为audience
@ConfigurationProperties(prefix="audience")
@Component
@ApiModel(value="JWT")
public class Audience {

	@ApiModelProperty(value="传入的客户端id,相当于微信的openID",required=true)
	private String clientId;
	@ApiModelProperty(value="64位公钥",required=true)
	private String base64Secret;
	@ApiModelProperty(value="令牌发行者姓名",required=true)
	private String name;
	@ApiModelProperty(value="令牌有效时间,单位为秒",required=true)
	private int expiresSecond;
}

一、在用户登录是生成token,返回给客户端

String accessToken=JwtUtils.createJWT(loginParamter, user, audience);

二、在用户下次请求是验证token

	private boolean isValidJwt(HttpServletRequest request){
		LOGGER.info("{} request to {}",request.getMethod(),request.getRequestURL());
		String authorization=request.getHeader("Authorization");
		LOGGER.info("authorization is: {}",authorization);
		//access_token的头信息,定义为bearer
		String headString=authorization.substring(0, 6).toLowerCase();
		//compareTo逐个比较两个字符串中相对字符的ascll值,所有字符都相同返回0,发现小于时返回正整数,大于时返回负整数,即ascll值的差值。
		if(headString.compareTo(Constants.BEARER)==0){
			authorization=authorization.substring(6, authorization.length());
			if(JwtUtils.parseJWT(authorization, audience.getBase64Secret())!=null){
				return true;
			}
		}
		return false;
	}





使用 JSON Web Token (JWT) 实现登录的 Java 代码如下: 首先,需要引入以下依赖: ```xml <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> ``` 然后,可以编写一个 `JwtUtil` 类来实现 JWT 的生成和解析: ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; import java.security.Key; import java.util.Date; public class JwtUtil { private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); public static String generateToken(String subject, long expirationTimeMillis) { Date now = new Date(); Date expirationDate = new Date(now.getTime() + expirationTimeMillis); return Jwts.builder() .setSubject(subject) .setIssuedAt(now) .setExpiration(expirationDate) .signWith(key) .compact(); } public static String parseToken(String token) { Claims claims = Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); return claims.getSubject(); } } ``` 在上面的代码中,`generateToken` 方法用于生成 JWT,接受一个 `subject` 参数表示用户 ID,和一个 `expirationTimeMillis` 参数表示过期时间(以毫秒为单位)。`parseToken` 方法用于解析 JWT,返回其中的用户 ID。 接下来,可以编写一个简单的登录接口: ```java import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class LoginController { @PostMapping("/login") public ResponseEntity<String> login(@RequestBody User user) { if (authenticate(user)) { String token = JwtUtil.generateToken(user.getId(), 86400000); return ResponseEntity.ok(token); } else { return ResponseEntity.badRequest().build(); } } private boolean authenticate(User user) { // TODO: 实现验证逻辑 return true; } } ``` 在上面的代码中,`User` 是一个简单的 Java 类,包含一个字符串类型的 `id` 属性。`login` 方法接受一个 `User` 对象作为参数,调用 `authenticate` 方法进行验证。如果验证通过,则使用 `JwtUtil.generateToken` 方法生成 JWT 并返回;否则返回错误响应。 最后,可以编写一个使用 JWT 进行身份验证的接口: ```java import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/user") public ResponseEntity<String> getUser(@RequestHeader("Authorization") String authorizationHeader) { String token = authorizationHeader.substring(7); String userId = JwtUtil.parseToken(token); // TODO: 根据用户 ID 查询用户信息并返回 return ResponseEntity.ok("User ID: " + userId); } } ``` 在上面的代码中,`getUser` 方法接受一个名为 `Authorization` 的请求头,其中包含 JWT。首先从请求头中获取 JWT,并调用 `JwtUtil.parseToken` 方法解析其中的用户 ID。然后根据用户 ID 查询用户信息并返回。 注意,在实际应用中,需要对 JWT 进行安全性考虑,比如使用 HTTPS 协议传输、设置较短的过期时间、使用更复杂的密钥等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值