成都网站建设设计

将想法与焦点和您一起共享

JTW怎么实现认证与授权

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

创新互联自2013年创立以来,是专业互联网技术服务公司,拥有项目成都网站建设、网站建设网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元潍城做网站,已为上家服务,为潍城各地企业和个人服务,联系电话:13518219792

JWT理论部分

摘要

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

组成

JWT由三部分组成,详情如下图: JTW怎么实现认证与授权

  • 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
配置拦截器

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

@Configuration
public 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/**",");
    }
添加配置请求拦截器
@Component
public 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。

@Configuration
public 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,则需要使用异常拦截器。

@ControllerAdvice
public 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怎么实现认证与授权”的内容了,经过本文的学习后,相信大家对JTW怎么实现认证与授权这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!


分享文章:JTW怎么实现认证与授权
网站链接:http://chengdu.cdxwcx.cn/article/ipseip.html