千家信息网

JTW怎么实现认证与授权

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,这篇文章主要讲解了"JTW怎么实现认证与授权",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"JTW怎么实现认证与授权"吧!JWT理论部分摘要是为了在网络
千家信息网最后更新 2025年01月23日JTW怎么实现认证与授权

这篇文章主要讲解了"JTW怎么实现认证与授权",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"JTW怎么实现认证与授权"吧!

JWT理论部分

摘要

是为了在网络应用环境中传递声明而执行的一种基于json的开放标准。特别适合分布式站点的单点登录场景。jwt的声明一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息,以便于从服务器获取资源,也可以增加一些额外的其他业务逻辑所用到的生命信息。

组成

JWT由三部分组成,详情如下图:

  • header:头部

alg表示签名的生成算法。 typ表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。

{        "alg":"HS256",        "typ":"JWT"}
  • payload:有效载荷

可选参数: iss: 签发者 sub: 面向用户 aud: 接收者 iat(issued at): 签发时间 exp(expires): 过期时间 nbf(not before):不能被接收处理时间,在此之前不能被接收处理 jti:JWT ID为web token提供唯一标识

{        "sub":"123456",        "exp":"1564641412"}
  • signature:签名

以header和payload生成的签名,防止header和payload被篡改。这里需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开, 解析时需要匹配密码(secret)才能解析成功。

String signature = HMACSHA512(base64UrlEncode(header)+"."+                                                                base64UrlEncode(payload),                                                                secret);

JWT 实践

pom文件引入相关依赖
        io.jsonwebtoken        jjwt        0.9.0
配置拦截器

需拦截除登录外所有接口,并开放静态路径

@Configurationpublic class WebConfig extends WebMvcConfigurationSupport {    @Autowired    private JwtInterceptor jwtInterceptor;    /**     * 配置静态资源     * @param registry     */    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        registry.addResourceHandler("/**")                .addResourceLocations("classpath:/static/");        registry.addResourceHandler("/swagger-ui.html")                .addResourceLocations("classpath:/META-INF/resources/");        registry.addResourceHandler("/webjars/**")                .addResourceLocations("classpath:/META-INF/resources/webjars/");        super.addResourceHandlers(registry);    }    /**     * 注册拦截器     * @param registry     */    @Override    public void addInterceptors(InterceptorRegistry registry) {        // 添加拦截的请求,并排除几个不拦截的请求        registry.addInterceptor(jwtInterceptor).addPathPatterns("/**")                .excludePathPatterns("/loginController/loginSystem","/swagger-ui.html",                                        "/static/**","/swagger-resources/**","/webjars/**",");    }
添加配置请求拦截器
@Componentpublic class JwtInterceptor extends HandlerInterceptorAdapter {    @Autowired    private JwtTokenConfig jwtTokenConfig;    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        String header = Constant.getContentProperties().getStringProperty("header");        //获取请求token        String reqToken = getJwt(request);        if (jwtTokenConfig.validateJwtToken(reqToken)) {            return true;        }        return false;    }    /**     * 获取并返回token信息     * @param request     * @return     */    private String getJwt(HttpServletRequest request) {        //从header中获取        String authHeader = request.getHeader("Authorization");        String header = Constant.getContentProperties().getStringProperty("header");        if (StringUtils.startsWith(authHeader, header)) {            authHeader = authHeader.replace(header+" ", "");        }        return authHeader;    }
添加JWT配置类

配置类用于生成、解析、校验Token。由于业务需求,token过期后将派发新的token。

@Configurationpublic class JwtTokenConfig {    private static final Logger logger = LoggerFactory.getLogger(JwtTokenConfig.class);    @Autowired    private JwtTokenMapper jwtTokenMapper;        //读取配置文件信息    private String expire = Constant.getContentProperties().getStringProperty("expire");    private String secret = Constant.getContentProperties().getStringProperty("secret");    private String header = Constant.getContentProperties().getStringProperty("header");    /**     * 生成token     * @param subject     * @return     */    public String generateToken(String subject) {        //设置过期时间        Date expireDate = new Date(System.currentTimeMillis() + 1000 * Long.parseLong(expire));        //组建header        Map headMap = new HashMap<>();        headMap.put("alg", SignatureAlgorithm.HS256.getValue());        headMap.put("typ", "JWT");        //自定义组件        Map claims = new HashMap<>();        claims.put("created", DateUtil.formatDate(new Date(),DateUtil.YEAR_TO_SECOND));        String access_token = Jwts.builder().setHeader(headMap)                                            .signWith(SignatureAlgorithm.HS512, secret)                                            .setClaims(claims)                                            //面向用户                                            .setSubject(subject)                                            //过期时间                                            .setExpiration(expireDate)                                            //生成token                                            .compact();        //刷新数据库中token信息        refreshToken(subject, access_token, expireDate);        logger.info(subject+" 生成后的token:"+access_token);        return access_token;    }    /**     * 获得签名信息     * @param token     * @return     */    public Claims getClaimsFromToken(String token) {        Claims claims = null;        try {            claims = Jwts.parser()                    .setSigningKey(secret)                    .parseClaimsJws(token)                    .getBody();            logger.info("解析token结果:"+claims);        } catch (ExpiredJwtException e) {            //token过期创建并返回一个新token            logger.info("token过期,正在创建新token\n");            JwtToken jwtToken = jwtTokenMapper.selectByToken(token);            if(jwtToken != null){                String newToken = generateToken(jwtToken.getUserCode());                claims = Jwts.parser()                        .setSigningKey(secret)                        .parseClaimsJws(newToken)                        .getBody();                logger.info("解析token结果:"+claims);            } else{                logger.info("token无效");            }        } catch (Exception e){            logger.info("解析异常");        }        return claims;    }    /**     * token校验     * @param token     * @return     */    public boolean validateJwtToken(String token){        if(StringUtils.isNotBlank(token)){            //获得token中signature信息,并验证过期时间            Claims claims = getClaimsFromToken(token);            JwtToken jwtToken = jwtTokenMapper.selectByUserCode(claims.getSubject());            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();            if(jwtToken == null || jwtToken.getJwtId() <= 0){                logger.info("token无效");            }                        //返回信息中将token添加至header中            response.setHeader("Authorization",header+" "+jwtToken.getToken());            return true;        } else{            logger.info("token为空");        }    }    /**     * 刷新数据库中token信息     * @param subject     * @param access_token     * @param expireDate     */    public void refreshToken(String subject, String access_token, Date expireDate){        //数据库中存储数据        jwtTokenMapper.deleteByUserCode(subject);        JwtToken jwtToken = new JwtToken();        jwtToken.setUserCode(subject);        jwtToken.setToken(access_token);        jwtToken.setCreateTime(new Date());        jwtToken.setExpireTime(expireDate);        jwtTokenMapper.insertSelective(jwtToken);    }}
统一处理拦截器中异常

拦截器中出现异常后,通常会使用系统默认方式返回,若想自定义返回json,则需要使用异常拦截器。

@ControllerAdvicepublic class ExceptionInterceptor {    @ExceptionHandler(value = Exception.class)    @ResponseBody    public Map allExceptionHandler(Exception e){        Map resultMap = new HashMap<>(2);        if(e instanceof Exception){            resultMap.put("code", "500");            resultMap.put("msg", e.getMessage());        }        return resultMap;    }}
使用Swagger-UI测试结果,token返回成功!

感谢各位的阅读,以上就是"JTW怎么实现认证与授权"的内容了,经过本文的学习后,相信大家对JTW怎么实现认证与授权这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0