发表于: 2018-10-19 21:04:03

1 340


今天完成的事情

1.解决昨天的bug,直接加一个ip-address指定ip地址即可

2.学习翁涵大佬的权限模块

zuul网关配置

spring:
 application:
   name: appi-zuul
redis:
   # Redis数据库索引(默认为0
   database: 0
   # Redis服务器地址
   host: 127.0.0.1
# Redis服务器连接端口
   port: 6379
   # Redis服务器连接密码(默认为空)
   password:
   jedis:
     pool:
     # 连接池最大连接数(使用负值表示没有限制)
       max-active: 20
       # 连接池中的最大空闲连接
       max-idle: 10
       # 连接池中的最小空闲连接
       min-idle: 5

server:
 port: 5555
zuul:
 routes:
   rbac:
     path: /a/rbac/**
serviceId: rbac-service

eureka:
 client:
   service-url:
     defaultZone: http://127.0.0.1:1111/eureka/


过滤逻辑:

package com.wh.demozull.accessfilter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.wh.demozull.utils.JwtUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.RedisTemplate;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
* @Author: 快乐水 樱桃可乐
* @Description:
* @Date: Created in 13:09 2018/9/30
* @Modified By:
*/
public class ReceptionFilter extends ZuulFilter {
private static final String key = "Happywater";

   private static Logger logger = LoggerFactory.getLogger(BackstageFilter.class);

   @Autowired
   private RedisTemplate redisTemplate;

   @Override
   public String filterType() {
return FilterConstants.ROUTE_TYPE;
   }

@Override
   public int filterOrder() {
return 1;
   }

@Override
   public boolean shouldFilter() {
RequestContext context = RequestContext.getCurrentContext();
       HttpServletRequest request=context.getRequest();
       //获取url的路径
       String path=request.getRequestURI();
       //url进行分割
       String[] uriList=path.split("/");

       //如果是后台路径则放行
       if("a".equals(uriList[1])){
return false;
       }
//如果是不需要登录的路径则放行
       if("o".equals(uriList[3])){
return false;
       }

//其余的接口是:前台需要登录才能访问的接口,进入run过滤器
       return true;
   }

@Override
   public Object run() throws ZuulException {
RequestContext context=RequestContext.getCurrentContext();
       HttpServletRequest request=context.getRequest();
       //获取路径
       String path=request.getRequestURI();
       //分割路径
       String[] uriList=path.split("/");

       //获取请求头中的JWT
       String jwt=request.getHeader("JWT");
       logger.info("jwt: "+jwt);

       //请求头中不存在JWT:未登录
       if(jwt==null){
logger.info("Token");
           context.put(FilterConstants.REQUEST_URI_KEY,"/reception/notJwt");
           return null;
       }

//使用Map获取jwt中的值
       Map map=JwtUtil.parseJWT(jwt,key);

       //JWT验证:取jwt中的值与密钥重创jwt,对比验证
       if(!JwtUtil.createJWT(map,key).equals(jwt)){
logger.info("JWT不可信");
           context.put(FilterConstants.REQUEST_URI_KEY,"/reception/UntrustworthyJwt");
           return null;
       }

//jwt中获取前台id:前台使用receptionId作为idkey
       Integer id=(Integer)map.get("receptionId");
       //通过前台idredis从库中获取redisJwt
       String redisJwt=(String) redisTemplate.opsForValue().get(id+"");
       logger.info("redisJwt: "+redisJwt);

       //如果redis中不存在对应的JWT,表明已注销
       if(redisJwt==null){
logger.info("已注销,请重新登录");
           context.put(FilterConstants.REQUEST_URI_KEY,"/reception/notCorrespondingJwt");
           return null;
       }

//用户的jwtredis中的jwt不相同,则表明请求头中的jwt已失效
       if(!jwt.equals(redisJwt)){
logger.info("jwt已过期");
           context.put(FilterConstants.REQUEST_URI_KEY,"/reception/invalidJwt");
           return null;
       }

//其余情况放行
       return null;
   }

}
package com.wh.demozull.accessfilter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.wh.demozull.utils.JwtUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.RedisTemplate;

import javax.jnlp.FileContents;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
* @Author: 快乐水 樱桃可乐
* @Description:
* @Date: Created in 9:45 2018/9/29
* @Modified By:
*/
public class BackstageFilter extends ZuulFilter {

private static final String key = "Happywater";

   private static Logger logger = LoggerFactory.getLogger(BackstageFilter.class);

   @Autowired
   private RedisTemplate redisTemplate;

   @Override
   public String filterType() {
//返回字符串代表过滤的类型,在zuul中定义了四种不同生命周期的过滤类型
       //1.pre:路由之前,FilterConstants.PRE_TYPE;
       //2.routing:路由之时,FilterConstants.ROUTE_TYPE;
       //3.post:路由之后,FilterConstants.POST_TYPE;
       //4.error:发送错误调用,FilterConstants.ERROR_TYPE;
       return FilterConstants.ROUTE_TYPE;
   }

@Override
   public int filterOrder() {
//过滤的顺序
       return 0;
   }

@Override
   public boolean shouldFilter() {
//写逻辑判断,是否要过滤,如果为True则过滤
       RequestContext context = RequestContext.getCurrentContext();
       HttpServletRequest request=context.getRequest();
       //获取url的路径
       String path=request.getRequestURI();
       String[] uriList=path.split("/");

       //如果是前台路径直接放行
       if("u".equals(uriList[1])){
return false;
       }

//如果是后台登录的路径则直接放行
       if("login".equals(uriList[3])){
return false;
       }
//如果是后台接口(除后台登陆外),则进入拦截器
       return true;
   }

@Override
   public Object run() throws ZuulException {
//过滤器的具体逻辑。可用很复杂,包括查sqlnosql去判断该请求到底有没有权限访问
       RequestContext context=RequestContext.getCurrentContext();
       HttpServletRequest request=context.getRequest();
       //获取请求路径
       String path=request.getRequestURI();
       //分割路径,获取uri
       String[] uriList=path.split("/");

       //Header中获取jwt
       String jwt=request.getHeader("JWT");
       logger.info("jwt: "+jwt);

       //请求头中不存在JWT
       if(jwt==null){
logger.info("Token");
           context.put(FilterConstants.REQUEST_URI_KEY,"/backstage/notJwt");
           return null;
       }

//解密JWT,保存到map对象中
       Map map=JwtUtil.parseJWT(jwt,key);

       //JWT验证:取jwt中的值与密钥重创jwt,对比验证
       if(!JwtUtil.createJWT(map,key).equals(jwt)){
//不对应表示:请求头中的JWT不可信
           logger.info("JWT不可信");
           context.put(FilterConstants.REQUEST_URI_KEY,"/backstage/UntrustworthyJwt");
           return null;
       }

//获取后台JWT中的ID
       Integer id=(Integer)map.get("backstageId");
       logger.info("当前操作者的id: "+id);
       //redis中获取对应IDJWT
       String redisJwt=(String) redisTemplate.opsForValue().get("backstageId"+id+"");
       logger.info("redisJwt: "+redisJwt);

       //redis中无对应的jwt表明,已注销
       if(redisJwt==null){
logger.info("已注销,请重新登录");
           context.put(FilterConstants.REQUEST_URI_KEY,"/backstage/notCorrespondingJwt");
           return null;
       }

//用户的jwtredis中的jwt不相同,表明请求头中的JWT已失效,通过此步代表登录成功
       if(!jwt.equals(redisJwt)){
logger.info("jwt已过期");
           context.put(FilterConstants.REQUEST_URI_KEY,"/backstage/invalidJwt");
           return null;
       }

//如果是注销操作或获取左边栏操作则直接放行(不需要权限验证)
       if("logout".equals(uriList[3])||"modules".equals(uriList[3])){
return null;
       }

//获取权限URI
       int size=uriList.length;
       String permission;
       //判断最后一个url是否为纯数字
       if(StringUtils.isNumeric(uriList[size-1])){
permission=uriList[size-3];
       }else{
permission=uriList[size-2];
       }

logger.info("访问该接口需要的权限: "+permission);

       //获取当前账户jwt中的权限集合
       List<String> authority= (List) map.get("authority");

       logger.info("用户具有的权限数量为: "+authority.size());
       //遍历权限,查看是否存在接口所需的权限
       if(authority.size()!=0) {
for (String s : authority) {
logger.info("用户具有的权限: " + s);
               if (s.equals(permission)) {
logger.info("具有权限");
                   //如果有匹配的权限,放行
                   return null;
               }
}
}

//设置没需要的权限,要跳转的路径
       context.put(FilterConstants.REQUEST_URI_KEY,"/backstage/notAuthority");
       return null;
   }
}

JWT的工具类的编写

package com.wh.demozull.utils;

import com.google.gson.Gson;
import com.wh.demozull.accessfilter.BackstageFilter;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
* @Author: 快乐水 樱桃可乐
* @Description:
* @Date: Created in 18:06 2018/9/28
* @Modified By:
*/
public class JwtUtil {

private static Logger logger = LoggerFactory.getLogger(BackstageFilter.class);

   /**
    * 解密
    * @param jsonWebToken
    * @param base64Security
    * @return
    */
   public static Claims parseJWT(String jsonWebToken, String base64Security) {
try {
Claims claims = Jwts.parser()
.setSigningKey(base64Security.getBytes())
.parseClaimsJws(jsonWebToken).getBody();
           return claims;
       } catch (Exception ex) {
logger.info("解密异常");
           return null;
       }
}

/**
    * 前三个参数为自己用户token的一些信息比如id,权限,名称等。不要将隐私信息放入(大家都可以获取到)
    * @param map
    * @param base64Security
    * @return
    */
   public static String createJWT(Map<String, Object> map, String base64Security) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
       //添加构成JWT的参数
       JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
.setPayload(new Gson().toJson(map))
//估计是第三段密钥
               .signWith(signatureAlgorithm,base64Security.getBytes());
       //生成JWT
       return builder.compact();
   }

public static void main(String[] args) {
Map<String, Object> map = new HashMap<String, Object>();
       map.put("province", "898765");
       map.put("city", "898765");
       map.put("appkey", "HMu1H/cmyKDOiHv41Y9lLROuOlOo+PPG8F4/RotRmNc=");
       map.put("timestamp", System.currentTimeMillis());

       //密钥
       String keyt = "Happywater";
       String token=JwtUtil.createJWT(map, keyt);
       System.out.println("JWT加密的结果:"+ token);
       System.out.println("JWT解密的结果:"+ parseJWT(token, keyt));
       Map map1=parseJWT(token,keyt);
       System.out.println(map1.get("city"));
   }
}

还有其他的还没看,明天再捋一捋


明天计划的事情

继续看权限模块的东西

遇到的问题

如上

收获

如上


返回列表 返回列表
评论

    分享到