权限与安全框架:Shiro+JWT整合(一)

依赖

	   <!--shrio-->
	   <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <!--jwt-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
        <!--工具类依赖-->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.11</version>
        </dependency>

工具类

在这里插入图片描述

  • JwtUtils:生成和解析token的工具类
public class JwtUtils {
    /**
     * 私钥加密token
     *
     * @param userInfo      载荷中的数据
     * @param privateKey    私钥
     * @param expireMinutes 过期时间,单位秒
     * @return
     * @throws Exception
     */
    public static String generateToken(UserInfo userInfo, PrivateKey privateKey, int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
    }

    /**
     * 私钥加密token
     *
     * @param userInfo      载荷中的数据
     * @param privateKey    私钥字节数组
     * @param expireMinutes 过期时间,单位秒
     * @return
     * @throws Exception
     */
    public static String generateToken(UserInfo userInfo, byte[] privateKey, int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey))
                .compact();
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥字节数组
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, byte[] publicKey) throws Exception {
        return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey))
                .parseClaimsJws(token);
    }

    /**
     * 获取token中的用户信息
     *
     * @param token     用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     * @throws Exception
     */
    public static UserInfo getInfoFromToken(String token, PublicKey publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toInt(body.get(JwtConstans.JWT_KEY_ID)),
                ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
        );
    }

    /**
     * 获取token中的用户信息
     *
     * @param token     用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     * @throws Exception
     */
    public static UserInfo getInfoFromToken(String token, byte[] publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toInt(body.get(JwtConstans.JWT_KEY_ID)),
                ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
        );
    }
}
  • RsaUtils:生成和获取公钥私钥的工具类
public class RsaUtils {
    /**
     * 从文件中读取公钥
     *
     * @param filename 公钥保存路径,相对于classpath
     * @return 公钥对象
     * @throws Exception
     */
    public static PublicKey getPublicKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        return getPublicKey(bytes);
    }

    /**
     * 从文件中读取密钥
     *
     * @param filename 私钥保存路径,相对于classpath
     * @return 私钥对象
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        return getPrivateKey(bytes);
    }

    /**
     * 获取公钥
     *
     * @param bytes 公钥的字节形式
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(byte[] bytes) throws Exception {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePublic(spec);
    }

    /**
     * 获取密钥
     *
     * @param bytes 私钥的字节形式
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(byte[] bytes) throws Exception {
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePrivate(spec);
    }

    /**
     * 根据密文,生存rsa公钥和私钥,并写入指定文件
     *
     * @param publicKeyFilename  公钥文件路径
     * @param privateKeyFilename 私钥文件路径
     * @param secret             生成密钥的密文
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(1024, secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        // 获取公钥并写出
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        writeFile(publicKeyFilename, publicKeyBytes);
        // 获取私钥并写出
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        writeFile(privateKeyFilename, privateKeyBytes);
    }

    private static byte[] readFile(String fileName) throws Exception {
        return Files.readAllBytes(new File(fileName).toPath());
    }

    private static void writeFile(String destPath, byte[] bytes) throws IOException {
        File dest = new File(destPath);
        if (!dest.exists()) {
            dest.createNewFile();
        }
        Files.write(dest.toPath(), bytes);
    }
}
  • JwtTokenUtils:给Cookie设置token的工具类
@Slf4j
public class JwtTokenUtils {

    /**
     * 给cookie设置jwtToken
     *
     * @param request
     * @param response
     * @param userSign:可以是id 或者 username(必须唯一) 通过id或者username找到唯一的user 然后生成UserInfo对象 设置到token里
     * @throws Exception
     */
    public static void setJwtToken(HttpServletRequest request, HttpServletResponse response, Object userSign) throws Exception {
        UserService userService=BeanUtils.getBean(UserService.class,request);
        JwtConfig jwtConfig=BeanUtils.getBean(JwtConfig.class,request);
        PrivateKey privateKey=RsaUtils.getPrivateKey(jwtConfig.getPriKeyPath());
        UserRoleService userRoleService=BeanUtils.getBean(UserRoleService.class,request);

        User user=null;
        if(userSign instanceof Integer){
            user=userService.getById((Serializable) userSign);
        }else if(userSign instanceof String){
            user=userService.getOne(QueryWapperUtils.getInWapper("name",(String) userSign));
        }else {
            log.info(JwtTokenUtils.class.getName()+"setJwtToken:error");
            return;
        }

        UserInfo userInfo=new UserInfo(user.getId(),user.getName());
        int roleId=userRoleService.getOne(QueryWapperUtils.getInWapper("user_id",user.getId())).getRoleId();

        //新生成token
        int expireTime=getExpireMinutes();
        String token=JwtUtils.generateToken(userInfo,privateKey,expireTime);
        CookieUtils.setCookie(request,response, jwtConfig.getCookieName(),token,null,null);
    }

    /**
     * 从request中直接读取cookie中的信息 然后重新设置到cookie中
     */
    public static void setJwtTokenByInfoFormCookie(HttpServletRequest request, HttpServletResponse response) throws Exception {
        UserInfo userInfo=getUserInfoFromToken(request);
        if(userInfo==null){
            log.info(JwtTokenUtils.class.getName()+"setJwtTokenByInfoFormCookie:error");
            return;
        }
        setJwtToken(request,response,userInfo.getId());
    }

    public static UserInfo getUserInfoFromToken(HttpServletRequest request){
        JwtConfig jwtConfig = BeanUtils.getBean(JwtConfig.class, request);
        String token= CookieUtils.getCookieValue(request,jwtConfig.getCookieName());
        UserInfo userInfo=null;
        try {
            PublicKey publicKey = RsaUtils.getPublicKey(jwtConfig.getPubKeyPath());
            userInfo= JwtUtils.getInfoFromToken(token,publicKey);
        } catch (Exception e) {
            log.info(JwtTokenUtils.class.getName()+"getUserInfoFromToken:error");
            return null;
        }
        return userInfo;
    }

    public static Set<String> getRolesSet(HttpServletRequest request){
        UserService userService=BeanUtils.getBean(UserService.class,request);
        RoleService roleService=BeanUtils.getBean(RoleService.class,request);
        UserRoleService userRoleService=BeanUtils.getBean(UserRoleService.class,request);

        Set<String> roles=new HashSet<>();
        UserInfo userInfo= JwtTokenUtils.getUserInfoFromToken(request);
        if(userInfo==null){
            return null;
        }
        User user=userService.getById(userInfo.getId());

        userRoleService.list(QueryWapperUtils.getInWapper("user_id",user.getId())).forEach(u_r->{
            UserRole userRole= (UserRole) u_r;
            Role role = roleService.getById(userRole.getRoleId());
            roles.add(role.getName());
        });

        return roles;
    }

    public static Set<String> getPermsSet(HttpServletRequest request){
        UserService userService=BeanUtils.getBean(UserService.class,request);
        RoleService roleService=BeanUtils.getBean(RoleService.class,request);
        PermissionService permissionService=BeanUtils.getBean(PermissionService.class,request);
        UserRoleService userRoleService=BeanUtils.getBean(UserRoleService.class,request);
        RolePermissionService rolePermissionService=BeanUtils.getBean(RolePermissionService.class,request);

        Set<String> perms=new HashSet<>();
        UserInfo userInfo= JwtTokenUtils.getUserInfoFromToken(request);;
        if(userInfo==null){
            return null;
        }
        User user=userService.getById(userInfo.getId());

        userRoleService.list(QueryWapperUtils.getInWapper("user_id",user.getId())).forEach(u_r->{
            UserRole userRole= (UserRole) u_r;
            Role role = roleService.getById(userRole.getRoleId());

            rolePermissionService.list(QueryWapperUtils.getInWapper("role_id", role.getId())).forEach(r_p->{
                RolePermission rolePermission= (RolePermission) r_p;
                Permission permission = permissionService.getById(rolePermission.getPermissionId());
                perms.add(permission.getName());
            });
        });

        return perms;
    }
}
  • BeanUtils:在util类获取不了bean
public class BeanUtils {
	
	/**
	 * 从上下文中获得bean
	 */ 
    public static <T> T getBean(Class<T> clazz, HttpServletRequest request){
        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return applicationContext.getBean(clazz);
    }
}
  • CodecUtils:加密的工具类
public class CodecUtils {


    /*
     * md5加密
     *  data:要加密的字符串
     *  salt:盐
     */
    public static String md5Hex(String data,String salt) {
        if (StringUtils.isBlank(salt)) {
            salt = data.hashCode() + "";
        }
        return DigestUtils.md5Hex(salt + DigestUtils.md5Hex(data));
    }

    /**
     *
     * @param data
     * @param times:次数
     * @return
     */
    public static String md5Hex(String data,Integer times){
        String res="";
        for(int i=0;i<times;i++){
            res+=DigestUtils.md5Hex(data);
        }
        return res;
    }

    /*
     *  sha加密
     *  data:要加密的字符串
     *  salt:盐
     */
    public static String shaHex(String data, String salt) {
        if (StringUtils.isBlank(salt)) {
            salt = data.hashCode() + "";
        }
        return DigestUtils.sha512Hex(salt + DigestUtils.sha512Hex(data));
    }

    /*
     * 生成盐
     */
    public static String generateSalt(){
        return StringUtils.replace(UUID.randomUUID().toString(), "-", "");
    }
}

  • CookieUtils:设置cookie的util
/**
 *
 * Cookie 工具类
 *
 */
public final class CookieUtils {

    static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);

    /**
     * 得到Cookie的值, 不编码
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName) {
        return getCookieValue(request, cookieName, false);
    }

    /**
     * 得到Cookie的值,
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
        Cookie[] cookieList = request.getCookies();
        if (cookieList == null || cookieName == null){
            return null;
        }
        String retValue = null;
        try {
            for (int i = 0; i < cookieList.length; i++) {
                if (cookieList[i].getName().equals(cookieName)) {
                    if (isDecoder) {
                        retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
                    } else {
                        retValue = cookieList[i].getValue();
                    }
                    break;
                }
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("Cookie Decode Error.", e);
        }
        return retValue;
    }

    /**
     * 得到Cookie的值,
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
        Cookie[] cookieList = request.getCookies();
        if (cookieList == null || cookieName == null){
            return null;
        }
        String retValue = null;
        try {
            for (int i = 0; i < cookieList.length; i++) {
                if (cookieList[i].getName().equals(cookieName)) {
                    retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
                    break;
                }
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("Cookie Decode Error.", e);
        }
        return retValue;
    }

    /**
     * 生成cookie,并指定编码
     * @param request 请求
     * @param response 响应
     * @param cookieName name
     * @param cookieValue value
     * @param encodeString 编码
     */
    public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, String encodeString) {
        setCookie(request,response,cookieName,cookieValue,null,encodeString, null);
    }

    /**
     * 生成cookie,并指定生存时间
     * @param request 请求
     * @param response 响应
     * @param cookieName name
     * @param cookieValue value
     * @param cookieMaxAge 生存时间
     */
    public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge) {
        setCookie(request,response,cookieName,cookieValue,cookieMaxAge,null, null);
    }

    /**
     * 设置cookie,不指定httpOnly属性
     */
    public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString) {
        setCookie(request,response,cookieName,cookieValue,cookieMaxAge,encodeString, null);
    }

    /**
     * 设置Cookie的值,并使其在指定时间内生效
     *
     * @param cookieMaxAge
     *            cookie生效的最大秒数
     */
    public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString, Boolean httpOnly) {
        try {
            if(StringUtils.isBlank(encodeString)) {
                encodeString = "utf-8";
            }

            if (cookieValue == null) {
                cookieValue = "";
            } else {
                cookieValue = URLEncoder.encode(cookieValue, encodeString);
            }
            Cookie cookie = new Cookie(cookieName, cookieValue);
            if (cookieMaxAge != null && cookieMaxAge>0)
                cookie.setMaxAge(cookieMaxAge);
            if (null != request)// 设置域名的cookie
                cookie.setDomain(getDomainName(request));
            cookie.setPath("/");

            if(httpOnly != null) {
                cookie.setHttpOnly(httpOnly);
            }
            response.addCookie(cookie);
        } catch (Exception e) {
            logger.error("Cookie Encode Error.", e);
        }
    }

    /**
     * 得到cookie的域名
     */
    private static final String getDomainName(HttpServletRequest request) {
        String domainName = null;

        try{
            if(request.getMethod().toUpperCase().equals("GET")){
                domainName=request.getHeader("Referer").split("/")[2];
            }else {
                domainName=request.getHeader("Origin").split("//")[1];
            }
        }catch (NullPointerException e){
            domainName=request.getHeader("Host").split(":")[0];
            if(StringUtils.isBlank(domainName)){
                throw new RuntimeException("无法获得设置cookie的domain");
            }
        }
        return domainName;
    }

}

  • QueryWapperUtils:mybatis-plus生成查询条件的工具类
public class QueryWapperUtils {

    public static QueryWrapper getInWapper(String colum,Object... s){
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.in(colum,s);
        return queryWrapper;
    }

    public static QueryWrapper getLikeWapper(String colum,Object s){
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.like(colum,s);
        return queryWrapper;
    }

}

相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:马嘣嘣 返回首页