【问题标题】:Authentication using jwt how to validate http requests使用 jwt 进行身份验证如何验证 http 请求
【发布时间】:2023-03-10 06:39:01
【问题描述】:

我正在使用 Spring Boot 编写 Web 应用程序。它是基于 jwt 身份验证的 我有模型用户、教师、学生、课程。教师和学生扩展用户

@Entity
public class User {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   private String username;
   @ManyToMany(fetch = FetchType.LAZY)
   @JoinTable(name = "user_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
   private Set<Role> roles = new HashSet<>();
   // Other fields and getters setters
}

@Entity
public class Course {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;   
   @ManyToOne
   @JoinColumn(name = "teacher_id", nullable = false)
   private Teacher teacher;

   @ManyToMany(mappedBy = "enrolledCourses")
   private Set<Student> students;
   // Other fields and getters setters
}

@Entity
public class Teacher extends User{
   @OneToMany(mappedBy = "teacher")
   private Set<Course> courses;
   // Other fields and getters setters
}


@Entity
public class Student extends User{
   @ManyToMany
   @JoinTable(
        name = "course_student",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id"))
   private Set<Course> enrolledCourses;
   // Other fields and getters setters
}

我还有课程 Api,我在其中实现了发布、放置、删除、更新和 这些方法必须仅供教师用户使用。 我的课程 Api 是这样的

@RestController
@RequestMapping("/teachers")
@PreAuthorize("hasRole('TEACHER')")
public class TeacherCourseController {

   @GetMapping("/{teacherId}/courses")
   public Set<Course> getCourse(@PathVariable("teacherId") Teacher teacher){
    // code
   }
   @PostMapping("/{teacherId}/courses")
   public Course createCourse(
        @PathVariable("teacherId") Long teacherId,
        @ModelAttribute CourseDto courseDto){
   // code
   }
   @PutMapping("/{teacherId}/courses/{courseId}")
   @JsonView(Views.IdName.class)
   public Course updateCourse(
        @ModelAttribute CourseDto courseDto,
        @PathVariable("courseId") Course courseFromDb){
    // code
   }
   @DeleteMapping("/{teacherId}/courses/{courseId}")
   public void getCourse(@PathVariable("courseId") Course course) throws IOException {
    // code
   }
}

我的 api 网址变得更糟,看起来像这样 http://localhost:8080/teachers/{teacherId}/courses/{courseId} 我如何检查老师是否要求他的课程而不是其他老师。谢谢

【问题讨论】:

    标签: spring-boot http security authentication jwt


    【解决方案1】:

    为什么不让课程成为顶级资源?您将拥有类似/courses{courseId} 的路径。在处理程序方法中,您检查来自对请求进行身份验证的 JWT 令牌的 sub 声明。如果声明与授课教师的教师 ID 不匹配,您将返回 403 Forbidden 响应。

    尽管课程是由老师教授的,但它们应该是他们自己的顶级资源是有道理的,因为学生可能会列出它们并注册它们。

    【讨论】:

      【解决方案2】:

      如果你有成功的spring安全配置:

      • 网页登录
      • 令牌生成
      • 在每个 api 调用中将令牌作为标头传递

      您必须有权访问 spring 安全上下文才能获取调用您的 rest 端点的用户的电子邮件:

      Authentication auth = SecurityContextHolder.getContext().getAuthentication();
      String name = auth.getName(); //get logged in username
      

      使用真实的电子邮件(由于您在调用 api 之前进行了 Web 登录)和对数据库的查询,您可以确保教师只请求其课程,如果没有则显示和错误:您无权访问此课程.

      建议:只列出我的课程

      如果是和端点仅用于简单教师,请勿将teacherId设置为参数:

      http://localhost:8080/teacher/courses/{courseId}
      

      此teacherId 不是必需的,因为您可以使用spring security context 获取老师的(真实电子邮件)并使用老师电子邮件而不是teacherId 搜索课程

      建议:我是管理员,我需要查看我所有老师的课程

      在这种情况下,您的端点是完全有效的:

      http://localhost:8080/teachers/{teacherId}/courses/{courseId}
      

      【讨论】:

      • 我认为我应该在称为请求过滤器的东西中验证请求,这样我就不会在每个休息方法(获取、更新、删除、放置)中都这样做。你觉得怎么样?
      • 是的,但仅通过 /teacher 端点请求文件管理器。默认情况下,请求过滤器适用于您的 api 的所有端点。一种更优雅的方法是对您的方法进行注释,例如预授权 (roytuts.com/…) (dreamix.eu/blog/java/…) 或创建一个新方法!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-07
      • 2014-09-06
      • 2017-11-11
      • 2023-03-31
      • 1970-01-01
      • 2019-08-07
      • 1970-01-01
      相关资源
      最近更新 更多