一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - Spring實現擁有者權限驗證的方法示例

Spring實現擁有者權限驗證的方法示例

2021-07-20 16:08喵先生的進階之路 Java教程

這篇文章主要介紹了Spring實現擁有者權限驗證的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

問題描述

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

實體關系

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

Spring實現擁有者權限驗證的方法示例

實現思路

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

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

注解

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

?
1
2
3
4
5
6
7
8
9
@target(elementtype.method)     // 注解使用在方法上
@retention(retentionpolicy.runtime) // 運行時生效
public @interface authorityannotation {
  /**
   * 倉庫名
   */
  @required
  class repository();
}

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

實體

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

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

Spring實現擁有者權限驗證的方法示例

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

?
1
2
3
public interface baseentity {
  list<user> getbelongtousers();
}

教師:

?
1
2
3
4
5
6
7
8
9
10
@entity
public class teacher implements yunzhientity, baseentity {
  ...
  @override
  public list<user> getbelongtousers() {
    list<user> userlist = new arraylist<>();
    userlist.add(this.getuser());
    return userlist;
  }
}

班級:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@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;
  }
}

學生:

?
1
2
3
4
5
6
7
8
@entity
public class student implements baseentity {
  ...
  @override
  public list<user> getbelongtousers() {
    return this.getklass().getbelongtousers();
  }
}

切面

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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對象。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@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獲取對象,然后獲取他的所屬用戶,再與當前登錄用戶進行比較。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@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。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@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);
  }
}

出現的問題

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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。這樣在序列化的時候就會忽略它。

?
1
2
3
4
5
6
7
8
9
10
@entity
public class student implements baseentity {
  ......
  @jsonignore
  @override
  public list<user> getbelongtousers() {
    return this.getklass().getbelongtousers();
 
  }
}

修改后的學生實體如上,其他實現了getbelongtousers方法的,都需要做相同處理。

總結

 以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://segmentfault.com/a/1190000018442618

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 性印度freehd | 四虎影视4hu最新地址在线884 | 亚洲国产精品第一页 | 国产精品酒店视频免费看 | 美女被狂揉下部羞羞动漫 | 动漫白丝袜美女羞羞 | 亚洲高清无在码在线电影 | 国产成人精品免费久久久久 | 桃乃木香在线 | 福利一区福利二区 | 色碰视频| 性xxx免费 | 久久爽狠狠添AV激情五月 | 免费午夜网站 | 四虎影视在线看免费 720p | 趴好撅高打屁股sp调教h | 情欲综合网| 天美传媒tm0087 | 亚洲欧美日韩另类在线一 | 天天做天天爱天天爽综合网 | 国产精品亚洲专区一区 | 涩涩屋在线观看 | 国内精品福利丝袜视频_速 国内精品91久久久久 | 学校女性奴sm训练调教 | 精品成人一区二区三区免费视频 | 国产黄频在线观看 | 热久久最新网址 | 99久久99热久久精品免费看 | 我与旗袍老师疯狂床震 | caoporn国产 | 波多野结衣女老师 | 国产欧美一区二区成人影院 | 国产成人精品一区二三区 | 疯狂激吻添下边小说 | 国产精品香蕉一区二区三区 | 5g影院天天5g天天爽大陆 | 动漫美女被吸乳 | 女主被男主做哭失禁高h | 草草影院国产 | 95视频免费看片 | 日本漫画无翼乌 |