SpringBoot使用拦截器方式实现Jwt-token鉴权

1. 环境配置

pom.xml

		<!--jwt 依赖-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <!--数据库 和 JPA 依赖-->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

application.yml

server: 
  port: 9008 # 端口号 (与jwt无关)
spring: 
  application:  
    name: sunmone-user #指定服务名 (与jwt无关)
  datasource:  # 数据库配置(与jwt无关)
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/数据库名称?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
  jpa: # 使用JPA访问数据库(与jwt无关)
    database: MySQL
    show-sql: true
jwt: # jwt 自定义参数
  config:
    key: sunmone # 盐
    ttl: 3600000 # token过期时间 一小时

JWT 工具类

package utils;

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.
 */

@ConfigurationProperties("jwt.config") // 在 application.yml 中取 key 和 ttl的值
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);
        // 创建 token 令牌
        JwtBuilder builder = Jwts.builder().setId(id)
                .setSubject(subject) // jwt 指定的用户
                .setIssuedAt(now) // jwt 签发时间
                .signWith(SignatureAlgorithm.HS256, key).claim("roles", roles); //jwt 头部 和自定义角色权限
        // 如果 ttl大于0 设置token令牌过期时间
        if (ttl > 0) {
            builder.setExpiration( new Date( nowMillis + ttl));
        }
        // 返回 token 令牌
        return builder.compact();
    }
    /**
     * 解析JWT
     * @param jwtStr
     * @return
     */
    public Claims parseJWT(String jwtStr){
        // 解析令牌
        return  Jwts.parser()
                .setSigningKey(key) // 令牌的 盐
                .parseClaimsJws(jwtStr) // token 值
                .getBody();
    }
}

Application 启动类

@SpringBootApplication
public class UserApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
    // 创建 JWT Utils对象
    @Bean
    public JwtUtil jwtUtil() {
        return new JwtUtil();
    }
}

2. JWT配置

如果我们每个方法都去写一段代码,冗余度太高,不利于维护,那如何做使我们的代码看起来更清爽呢?我们可以将这段代码放入拦截器去实现

拦截器和过滤器放在同一目录下即可

2.1 过滤器

import utils.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * JWT  拦截器
 * 在preHandle中,可以进行编码、安全控制等处理;前置拦截
 * 在postHandle中,有机会修改ModelAndView; 中间拦截
 * 在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。 异常拦截
 */
@Component // 把拦截器添加到Spring中
public class JwtFilter extends HandlerInterceptorAdapter {

    @Autowired
    private JwtUtil jwtUtil;

    /***
     * 重写 JWT前置拦截器,所有请求都会被拦截 所以要写一个extends WebMvcConfigurationSupport设置拦击规则
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // JWT 前置拦截器
        System.out.println("经过JwtFilter");

        // 前后端约定:前端请求服务时需要添加头信息Authorization ,内容为Bearer+空格+token
        // 获取 token 令牌
        String Authorization = request.getHeader("Authorization");
        // 如果 请求头不为空
        if (Authorization != null) {
            // 如果 参数中以 Bearer空格为开头
            if (Authorization.startsWith("Bearer ")) {
                // 取 token数据
                if (Authorization.length() > 8){
                    String token = Authorization.substring(7);
                    // 解析令牌获取 Claims对象
                    Claims claims = jwtUtil.parseJWT(token);//获取载荷
                    // 如果Claims不为空
                    if (claims != null) {
                        // 判断权限 加入到请求参数中
                        if (claims.get("roles").equals("admin")) {//管理员身份
                            request.setAttribute("admin_claims", claims);
                        }
                        // 判断权限 加入到请求参数中
                        if (claims.get("roles").equals("user")) {//普通用户
                            request.setAttribute("user_claims", claims);
                        }
                    }
                }
            }
        }
        // 始终放行 由具体资源来决定结果
        return true;
    }
}

2.2 拦截器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * 拦截器配置
 */
@Configuration // 配置类 继承 extends WebMvcConfigurationSupport
public class ApplicationConfig extends WebMvcConfigurationSupport {

    // 加载 jwt拦截器
    @Autowired
    private JwtFilter jwtFilter;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 加载过滤器 除了login方法其余全部拦截
        registry.addInterceptor(jwtFilter)
                .addPathPatterns("/**")
                .excludePathPatterns("/**/login");
    }
}

3. Controller层鉴权

我们使用了前置拦截器,所有请求经过都会被拦截,除了login请求,那么只需要在Controller层把参数获取,判断用户就可以进行权限鉴定了

@RestController
@CrossOrigin
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private JwtUtil jwtUtil;
    
     /**
     * 删除
     *
     * @param id
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Result delete(@PathVariable String id) {
        // 有前置拦截器 只需要获取 token参数即可
        Claims claims = (Claims) request.getAttribute("admin_claims");
        if (claims == null){
            return new Result(false, StatusCode.ACCESSERROR, "权限不足");
        }
        userService.deleteById(id);
        return new Result(true, StatusCode.OK, "删除成功");
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
前端可以通过发送HTTP请求时在请求头中携带JWT Token,后端Spring Boot的拦截器可以拦截请求并进行JWT Token校验。 具体实现步骤如下: 1. 前端需要在发送请求的时候,在请求头中添加Authorization字段,并将JWT Token作为值传递。 2. 后端需要编写一个拦截器来拦截请求并进行JWT Token校验。在拦截器中,可以使用Java JWT库来解析JWT Token,并校验Token的有效性。 3. 如果JWT Token校验成功,则将请求交给下一个拦截器或处理器处理。如果JWT Token校验失败,则可以返回一个错误响应。 下面是一个简单的JWT Token校验拦截器的示例代码: ```java import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class JwtInterceptor implements HandlerInterceptor { private static final String SECRET_KEY = "your_secret_key"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); try { Claims claims = Jwts.parser().setSigningKey(SECRET_KEY.getBytes()).parseClaimsJws(token).getBody(); // TODO: 根据需要进行校验 return true; } catch (Exception e) { // Token校验失败,返回错误响应 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } } else { // 请求头中没有Authorization字段,返回错误响应 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } } } ``` 在上面的代码中,我们使用了Java JWT库来解析JWT Token,并校验Token的有效性。我们可以根据需要进行更详细的校验,比如校验Token中的用户信息等。如果JWT Token校验失败,我们返回一个401 Unauthorized的错误响应,表示请求未经授权。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叫我三胖哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值