JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用 户和服务器之间传递安全可靠的信息。
一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。
common工程引入依赖
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwtartifactId>
<version>0.6.0version>
dependency>
common工程,创建util.JwtUtil
package util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* Created by Administrator on 2018/4/11.
*/
@Component
@ConfigurationProperties("jwt.config")
public class JwtUtil {
private String key ;
private long ttl ;//一个小时
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public long getTtl() {
return ttl;
}
public void setTtl(long ttl) {
this.ttl = ttl;
}
/**
* 生成JWT
*
* @param id
* @param subject
* @return
*/
public String createJWT(String id, String subject, String roles) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder().setId(id)
.setSubject(subject)
.setIssuedAt(now)
.signWith(SignatureAlgorithm.HS256, key).claim("roles", roles);
if (ttl > 0) {
builder.setExpiration( new Date( nowMillis + ttl));
}
return builder.compact();
}
/**
* 解析JWT
* @param jwtStr
* @return
*/
public Claims parseJWT(String jwtStr){
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwtStr)
.getBody();
}
}
添加配置到要引用JwtUtil工具类工程的application.yml
jwt:
config:
key: shenhaiyu
ttl: 360000
配置bean 修改对应工程Application类
@Bean
public JwtUtil jwtUtil(){
return new util.JwtUtil();
}
修改AdminController的login方法
@Autowired
private JwtUtil jwtUtil;
@RequestMapping(value="/login",method = RequestMethod.POST)
public Result login(@RequestBody Admin admin){
Admin adminLogin= adminService.login(admin);
if(adminLogin==null){
return new Result(false,StatusCode.ERROR,"登录失败");
}
//采取使前后端可以通话,利用JWT
String token=jwtUtil.createJWT(adminLogin.getId(),adminLogin.getLoginname(),"admin");
Map<String,Object> map=new HashMap<>();
map.put("token",token);
map.put("role","admin");
return new Result(true,StatusCode.OK,"登陆成功",map);
}
测试运行结果
{ "flag": true,
"code": 20000,
"message": "登陆成功",
"data": { "token":
"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5ODQzMjc1MDc4ODI5MzgzNjgiLCJzdWIiOiJ4aWF
vbWkiLCJpYXQiOjE1MjM1MjQxNTksInJvbGVzIjoiYWRtaW4iLCJleHAiOjE1MjM1MjQ1MTl9
._YF3oftRNTbq9WCD8Jg1tqcez3cSWoQiDIxMuPmp73o", "name":"admin" }
}
Base64编码方式是可逆的,也就是透过编码后发放的Token内容是可以被解析的。一般而言,我们都不建议在有效载荷内放敏感讯息,比如使用者的密码。
1、无状态JWT令牌(Stateless JWT Token)发放出去之后,不能通过服务器端让令牌失效,必须等到过期时间过才会失去效用。2、假设在这之间Token被拦截,或者有权限管理身份的差异造成授权Scope修改,都不能阻止发出去的Token失效并要求使用者重新请求新的Token。
有权限管理的服务,管理用户的各种权限,及可访问路径等,在网关zuul中利用Pre过滤器,拦截一切请求,在过滤器中,解析jwt,获取用户身份,查询用户权限,判断用户身份可以访问当前路径。
答:
我们的微服务在网关的后面,而且整个服务被Nginx反向代理微服务暴露的可能性低。我们的微服务都做了严格的服务间鉴权处理,任何对微服务的访问都会被验证是否有授权,如果没有则会被拦截。