91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Spring中實現擁有者權限驗證

發布時間:2021-05-07 16:52:32 來源:億速云 閱讀:109 作者:Leah 欄目:編程語言

今天就跟大家聊聊有關怎么在Spring中實現擁有者權限驗證,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

問題描述

在做權限驗證的時候,我們經常會遇到這樣的情況:教師擁有多個學生,但是在處理學生信息的時候,教師只能操作自己班級的學生。所以,我們要做的就是,當教師嘗試處理別的班的學生的時候,拋出異常。

實體關系

用戶1:1教師,教師m:n班級,班級1:n學生

怎么在Spring中實現擁有者權限驗證

實現思路

findById為例。因為從整體上看,用戶學生m:n的關系,所以在調用這個接口的時候,獲取該學生的所有用戶,然后跟當前登錄用戶進行對比,如果不在其中,拋出異常。

利用切面,我們可以在findByIdupdatedelete方法上進行驗證。

注解

我們會在方法上添加注解,以表示對該方法進行權限驗證。

@Target(ElementType.METHOD)     // 注解使用在方法上
@Retention(RetentionPolicy.RUNTIME) // 運行時生效
public @interface AuthorityAnnotation {
  /**
   * 倉庫名
   */
  @Required
  Class repository();
}

因為我們需要獲取出學生,但是并不限于學生,所以就要將倉庫repository作為一個參數傳入。

實體

上面我們說過,需要獲取學生中的用戶,所以我們可以在實體中定義一個方法,獲取所有有權限的用戶:getBelongUsers()

但是,我們知道,學生和用戶沒用直接的關系,而且為了復用,在對其他實體進行驗證的時候也能使用,可以考慮創建一個接口,讓需要驗證的實體去實現他。

怎么在Spring中實現擁有者權限驗證

這樣,我們可以在讓每個實體都集成這個接口,然后形成鏈式調用,這樣就解決了上面你的兩個問題。

public interface BaseEntity {
  List<User> getBelongToUsers();
}

教師:

@Entity
public class Teacher implements YunzhiEntity, BaseEntity {
  ...
  @Override
  public List<User> getBelongToUsers() {
    List<User> userList = new ArrayList<>();
    userList.add(this.getUser());
    return userList;
  }
}

班級:

@Entity
public class Klass implements BaseEntity {
  ...
  @Override
  public List<User> getBelongToUsers() {
    List<User> userList = new ArrayList<>();
    for (Teacher teacher: this.getTeacherList()) {
      userList.addAll(teacher.getBelongToUsers());
    }

    return userList;
  }
}

學生:

@Entity
public class Student implements BaseEntity {
  ...
  @Override
  public List<User> getBelongToUsers() {
    return this.getKlass().getBelongToUsers();
  }
}

切面

有了實體后,我們就可以建立切面實現驗證功能了。

@Aspect
@Component
public class OwnerAuthorityAspect {
  private static final Logger logger = LoggerFactory.getLogger(OwnerAuthorityAspect.class.getName());

  /**
   * 使用注解,并第一個參數為id
   */
  @Pointcut("@annotation(com.yunzhiclub.alice.annotation.AuthorityAnnotation) && args(id,..) && @annotation(authorityAnnotation)")
  public void doAccessCheck(Long id, AuthorityAnnotation authorityAnnotation) {   }
  
  @Before("doAccessCheck(id, authorityAnnotation)")
  public void before(Long id, AuthorityAnnotation authorityAnnotation) {
  }

首先,我們要獲取到待操作對象。但是在獲取對象之前,我們必須獲取到repository

這里我們利用applicationContext來獲取倉庫bean,然后再利用獲取到的bean,生成repository對象。

@Aspect
@Component
public class OwnerAuthorityAspect implements ApplicationContextAware {
  private ApplicationContext applicationContext = null;  // 初始化上下文
  ......
  @Before("doAccessCheck(id, authorityAnnotation)")
  public void before(Long id, AuthorityAnnotation authorityAnnotation) {
    logger.debug("獲取注解上的repository, 并通過applicationContext來獲取bean");
    Class<?> repositoryClass = authorityAnnotation.repository();
    Object object = applicationContext.getBean(repositoryClass);

    logger.debug("將Bean轉換為CrudRepository");
    CrudRepository<BaseEntity, Object> crudRepository = (CrudRepository<BaseEntity, Object>)object;
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }
}

該類實現了ApplicationContextAware接口,通過setApplicationContext函數獲取到了applicationContext

接下來,就是利用repository獲取對象,然后獲取他的所屬用戶,再與當前登錄用戶進行比較。

@Before("doAccessCheck(id, authorityAnnotation)")
public void before(Long id, AuthorityAnnotation authorityAnnotation) {
  logger.debug("獲取注解上的repository, 并通過applicationContext來獲取bean");
  Class<?> repositoryClass = authorityAnnotation.repository();
  Object object = applicationContext.getBean(repositoryClass);

  logger.debug("將Bean轉換為CrudRepository");
  CrudRepository<BaseEntity, Object> crudRepository = (CrudRepository<BaseEntity, Object>)object;

  logger.debug("獲取實體對象");
  Optional<BaseEntity> baseEntityOptional = crudRepository.findById(id);
  if(!baseEntityOptional.isPresent()) {
    throw new RuntimeException("對不起,未找到相關的記錄");
  }
  BaseEntity baseEntity = baseEntityOptional.get();

  logger.debug("獲取登錄用戶以及擁有者,并進行比對");
  List<User> belongToTUsers = baseEntity.getBelongToUsers();
  User currentLoginUser = userService.getCurrentLoginUser();
  Boolean havePermission = false;
  if (currentLoginUser != null && belongToTUsers.size() != 0) {
    for (User user: belongToTUsers) {
      if (user.getId().equals(currentLoginUser.getId())) {
        havePermission = true;
        break;
      }
  }

    if (!havePermission) {
      throw new RuntimeException("權限不允許");
    }
  }
}

使用

在控制器的方法上使用注解:@AuthorityAnnotation,傳入repository。

@RestController
@RequestMapping("/student")
public class StudentController {

  private final StudentService studentService;  // 學生

  @Autowired
  public StudentController(StudentService studentService) {
    this.studentService = studentService;
  }

  /**
   * 通過id獲取學生
   *
   * @param id
   * @return
   */
  @AuthorityAnnotation(repository = StudentRepository.class)
  @GetMapping("/{id}")
  @JsonView(StudentJsonView.get.class)
  public Student findById(@PathVariable Long id) {
    return studentService.findById(id);
  }
}

出現的問題

實現之后,進行單元測試的過程中出現了問題。

@Test
public void update() throws Exception {
  logger.info("獲取一個保存學生");
  Student student = studentService.getOneSaveStudent();
  Long id = student.getId();
  logger.info("獲取一個更新學生");
  Student newStudent = studentService.getOneUnSaveStudent();

  String jsonString = JSONObject.toJSONString(newStudent);
  logger.info("發送更新請求");
  this.mockMvc
    .perform(put(baseUrl + "/" + id)
      .cookie(this.cookie)
      .content(jsonString)
      .contentType(MediaType.APPLICATION_JSON_UTF8))
    .andExpect(status().isOk());
}

怎么在Spring中實現擁有者權限驗證

400的錯誤,說明參數錯誤,參數傳的是實體,看下傳了什么:

怎么在Spring中實現擁有者權限驗證

我們看到,這個字段并不是我們實體中的字段,但是為什么序列化的時候出現了這個字段呢?

原因是這樣的,我們在實體中定義了一個getBelongToUsers函數,然后JSONobject在進行序列化的時候會根據實體中的getter方法,獲取get后面的為key,也就是將belongToUsers看做了字段。

所以就出現了上面傳實體字段多出的情況,從而引發了400的錯誤。

解決

我們不想JSONobject在序列化的時候處理getBelongToUsers,就需要聲明一下,這里用到了注解:@JsonIgnore。這樣在序列化的時候就會忽略它。

@Entity
public class Student implements BaseEntity {
  ......
  @JsonIgnore
  @Override
  public List<User> getBelongToUsers() {
    return this.getKlass().getBelongToUsers();

  }
}

看完上述內容,你們對怎么在Spring中實現擁有者權限驗證有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

庆元县| 安龙县| 博野县| 锦州市| 扎鲁特旗| 建水县| 邓州市| 拜泉县| 册亨县| 达拉特旗| 尉氏县| 碌曲县| 资源县| 怀来县| 沂源县| 马尔康县| 辽宁省| 蒙阴县| 易门县| 同德县| 无极县| 印江| 木兰县| 鄂托克旗| 高雄市| 布拖县| 尖扎县| 平乐县| 伊川县| 天镇县| 革吉县| 陇西县| 临高县| 肥乡县| 泌阳县| 乐清市| 墨脱县| 土默特左旗| 乐业县| 鲁甸县| 吐鲁番市|