亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring Boot 集成Shiro的多realm實(shí)現(xiàn)以及shiro基本入門教程

 更新時(shí)間:2020年10月20日 08:46:35   作者:山水尚書  
這篇文章主要介紹了Spring Boot 集成Shiro的多realm實(shí)現(xiàn)以及shiro基本入門,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

情景

我的項(xiàng)目中有六個(gè)用戶角色(學(xué)校管理員,學(xué)生等),需要進(jìn)行分別登陸。如果在一個(gè)realm中,對(duì)controller封裝好的Token進(jìn)行Service驗(yàn)證,需要在此realm中注入六個(gè)數(shù)據(jù)庫(kù)操作對(duì)象,然后寫一堆if語(yǔ)句來(lái)判斷應(yīng)該使用那個(gè)Service服務(wù),然后再在驗(yàn)證方法(doGetAuthorizationInfo)中寫一堆if來(lái)進(jìn)行分別授權(quán),這樣寫不僅會(huì)讓代碼可讀性會(huì)非常低而且很難后期維護(hù)修改(剛寫完的時(shí)候只有上帝和你能看懂你寫的是什么,一個(gè)月之后你寫的是什么就只有上帝能看懂了)。
所以一定要配置多個(gè)realm來(lái)分別進(jìn)行認(rèn)證授權(quán)操作。shiro有對(duì)多個(gè)realm的處理,當(dāng)配置了多個(gè)Realm時(shí),shiro會(huì)用自帶的org.apache.shiro.authc.pam.ModularRealmAuthenticator類的doAuthenticate方法來(lái)進(jìn)行realm判斷,源碼:

protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
  assertRealmsConfigured();
  Collection<Realm> realms = getRealms();
  if (realms.size() == 1) {
   return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
  } else {
   return doMultiRealmAuthentication(realms, authenticationToken);
  }
 }

assertRealmsConfigured();的作用是驗(yàn)證realm列表是否為空,如果一個(gè)realm也沒有則會(huì)拋出IllegalStateException異常(爆紅:Configuration error: No realms have been configured! One or more realms must be present to execute an authentication attempt.)
當(dāng)realm只有一個(gè)時(shí)直接返回,當(dāng)realm有多個(gè)時(shí)返回所有的realm。而我們要做的就是寫多個(gè)realm后重寫ModularRealmAuthenticator下的doAuthenticate方法,使它能滿足我們的項(xiàng)目需求。
那么改怎么重寫ModularRealmAuthenticator下的doAuthenticate方法,使它能滿足我們的項(xiàng)目需求呢?這就需要分析我們使用shiro的使用方法了。

shiro的使用

1.Controller層中,獲取當(dāng)前用戶后將用戶名和密碼封裝UsernamePasswordToken對(duì)象,然后調(diào)用Subject中的登陸方法subject.login(UsernamePasswordToken)

 @RequestMapping("/user/login")
	@ResponseBody
 public String Login(String userName,String password){
  //獲取當(dāng)前用戶 subject
  Subject subject = SecurityUtils.getSubject();
  //封裝用戶的登陸數(shù)據(jù)
  UsernamePasswordToken token = 
  new UsernamePasswordToken(userName, password);
  try{
   subject.login(token);//執(zhí)行登陸方法
   return "登陸成功";
  }catch (UnknownAccountException e){//用戶名不存在
   model.addAttribute("msg","用戶名不存在");
   return "用戶名不存在";
  }catch (IncorrectCredentialsException e){//密碼錯(cuò)誤
   model.addAttribute("msg","密碼錯(cuò)誤");
   return "密碼錯(cuò)誤";
  }
 }

(為了測(cè)試方便,我用了@ResponseBody返回字符串)
2.完善自定義Realm類,繼承于AuthorizingRealm,主要實(shí)現(xiàn)doGetAuthorizationInfo和doGetAuthenticationInfo方法
(需要實(shí)現(xiàn)認(rèn)證和授權(quán)方法,在這里方便測(cè)試主要是認(rèn)證)

public class StudentRealm extends AuthorizingRealm {
 @Resource
 private StudentsService studentsService;
 //授權(quán)
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  return null;
 }

 //認(rèn)證
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  System.out.println("Shiro=========Student認(rèn)證");
  UserToken userToken = (UserToken) token;
  Students students = studentsService.queryByNum(userToken.getUsername());
  //賬號(hào)不存在
  if (students == null) {
   System.out.println("學(xué)生不存在");
   //向上層提交UnknownAccountException異常,在controller層處理
   throw new UnknownAccountException();
  }
  //密碼認(rèn)證,shiro來(lái)做,可以自定義加密方式
  return new SimpleAuthenticationInfo("", students.getPassword(), USER_LOGIN_TYPE);
 }
}

3.配置shiro,將realm配置進(jìn)shiro(很多教程是使用xml配置或者ini配置,在這里用java代碼配置,功能都是一樣的,看個(gè)人習(xí)慣了)

@Configuration
public class ShiroConfig {
 @Bean
 public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
  ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
  //設(shè)置安全管理器
  bean.setSecurityManager(defaultWebSecurityManager);
  return bean;

 }

 //DefaultWebSecurityManager 默認(rèn)web安全管理器
 @Bean(name = "securityManager")
 public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
  DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  //關(guān)聯(lián)realm
  securityManager.setRealm(userRealm);
  return securityManager;
 }
 //創(chuàng)建自定義 realm
 @Bean
 public UserRealm userRealm() {
  return new UserRealm();
 }
}

記得加@Configuration注解?。。。。。?!

經(jīng)過(guò)以上三步,可以看出shiro的簡(jiǎn)略工作流程(非常簡(jiǎn)略)就是,在web 啟動(dòng)階段,讀取
@Configuration注解將自定義的ream配置進(jìn)默認(rèn)web安全管理器(DefaultWebSecurityManager)然后將DefaultWebSecurityManager與ShiroFilterFactoryBean相關(guān)聯(lián)。
當(dāng)用戶登陸時(shí),從前端拿到username和password,封裝好Token后,進(jìn)入realm進(jìn)行認(rèn)證和授權(quán),而realm就來(lái)自于剛才的shiro的DefaultWebSecurityManager配置

多realm實(shí)現(xiàn)原理

根據(jù)上面的shiro簡(jiǎn)略流程可知,shiro配置中寫入多個(gè)realm后,在controller提交token時(shí),只要多攜帶一個(gè)參數(shù),用來(lái)進(jìn)行org.apache.shiro.authc.pam.ModularRealmAuthenticator類的doAuthenticate(重寫后)的驗(yàn)證即可明確應(yīng)該用那個(gè)realm。那么,我們需要重寫org.apache.shiro.authc.UsernamePasswordToken(令其攜帶身份參數(shù)用于選擇realm)和org.apache.shiro.authc.pam.ModularRealmAuthenticator(令其根據(jù)token中的身份參數(shù)來(lái)進(jìn)行選擇realm)即可。

多realm實(shí)現(xiàn)具體操作

1.寫多個(gè)自定義的realm

public class AdminRealm extends AuthorizingRealm {

 @Resource
 private AdminService adminService;

 private static final String USER_LOGIN_TYPE = UserType.AdminRealm;

 @Override
 public String getName() {
  return UserType.AdminRealm;
 }

 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  return null;
 }

 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  System.out.println("Shiro=========Admin認(rèn)證");
  UserToken userToken = (UserToken) token;
  Admin admin = adminService.queryById(userToken.getUsername());
  if(admin == null){
   System.out.println("管理員不存在");
   throw new UnknownAccountException();
  }
  return new SimpleAuthenticationInfo("", admin.getAdminpassword(), USER_LOGIN_TYPE);
 }
}

2.創(chuàng)建靜態(tài)變量類(用于realm選擇)

public class UserType {
 //實(shí)習(xí)學(xué)校管理員
 public static final String SchoolAdminRealm = "schooladminrealm";

 //學(xué)生
 public static final String StudentRealm ="studentrealm";

 //管理員
 public static final String AdminRealm ="adminrealm_1";

 //導(dǎo)員
 public static final String InstructorRealm ="instructorrealm";

 //實(shí)習(xí)帶隊(duì)老師
 public static final String UniversityteacherRealm ="universityteacherrealm";

 //實(shí)習(xí)指導(dǎo)老師
 public static final String SchoolTeacherRealm ="schoolteacherrealm";
}

3.重寫UsernamePasswordToken,令其可以攜帶身份參數(shù)

@Component
public class UserModularRealmAuthenticator extends ModularRealmAuthenticator {

 @Override
 protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) {
  // 判斷getRealms()是否返回為空,ModularRealmAuthenticator 自帶
  assertRealmsConfigured();
  // 強(qiáng)制轉(zhuǎn)換回自定義的UserToken
  UserToken token = (UserToken) authenticationToken;
  String loginType = token.getLoginType();
  Collection<Realm> realms = getRealms();
   for (Realm realm : realms) {
    System.out.println(realm.getName().toLowerCase());
   if (realm.getName().toLowerCase().contains(loginType)){
   //找到登錄類型對(duì)應(yīng)的指定Realm
    return doSingleRealmAuthentication(realm, token);
   }
  }
  //沒找到正確的realm的異常處理
  String msg = "Configuration error: Didn't find the right realm";
  throw new IllegalStateException(msg);
 }
}

4.shiro的配置中寫入自定義的realm,還有其它配置

@Configuration
public class ShiroConfig {

 @Bean
 public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
  ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
  //設(shè)置安全管理器
  bean.setSecurityManager(defaultWebSecurityManager);
  return bean;
 }

 //DefaultWebSecurityManager
 @Bean(name = "securityManager")
 public DefaultWebSecurityManager getDefaultWebSecurityManager(
   @Qualifier("schoolAdminRealm") SchoolAdminRealm schoolAdminRealm,
   @Qualifier("studentRealm") StudentRealm studentRealm,
   @Qualifier("adminRealm") AdminRealm adminRealm,
   @Qualifier("schoolTeacherRealm") SchoolTeacherRealm schoolTeacherRealm,
   @Qualifier("instructorRealm") InstructorRealm instructorRealm,
   @Qualifier("universityteacherRealm") UniversityteacherRealm universityteacherRealm,
   @Qualifier("userModularRealmAuthenticator") UserModularRealmAuthenticator userModularRealmAuthenticator
 ) {
  DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  securityManager.setAuthenticator(userModularRealmAuthenticator);
  /**關(guān)聯(lián)realm
  *securityManager.setRealm() 是配置單個(gè)realm,不可用它配置多個(gè)realm
  *securityManager.setRealms()配置多個(gè)realm, 
  *List<Realm> realms可以直接被set進(jìn)去
  */
  List<Realm> realms = new ArrayList<Realm>();
  realms.add(schoolAdminRealm);
  realms.add(studentRealm);
  realms.add(adminRealm);
  realms.add(schoolTeacherRealm);
  realms.add(instructorRealm);
  realms.add(universityteacherRealm);
  securityManager.setRealms(realms);
  System.out.println(securityManager.getRealms().toString());
  return securityManager;
 }


 //實(shí)習(xí)學(xué)校管理員
 @Bean(name = "schoolAdminRealm")
 public SchoolAdminRealm SchoolAdminRealm() {
  return new SchoolAdminRealm();
 }

 //學(xué)生
 @Bean(name = "studentRealm")
 public StudentRealm StudentRealm() {
  return new StudentRealm();
 }

 //管理員
 @Bean(name = "adminRealm")
 public AdminRealm AdminRealm() {
  return new AdminRealm();
 }

 //導(dǎo)員
 @Bean(name = "instructorRealm")
 public InstructorRealm InstructorRealm() {
  return new InstructorRealm();
 }

 //實(shí)習(xí)帶隊(duì)老師
 @Bean(name = "universityteacherRealm")
 public UniversityteacherRealm UniversityteacherRealm() {
  return new UniversityteacherRealm();
 }

 //實(shí)習(xí)指導(dǎo)老師
 @Bean(name = "schoolTeacherRealm")
 public SchoolTeacherRealm SchoolTeacherRealm() {
  return new SchoolTeacherRealm();
 }

}

5.在controller中使用重寫后的UsernamePasswordToken(UserToken)即可

//管理員登陸
 @RequestMapping(value = "/AdminLogin", produces = "text/html;charset=UTF-8")
 @ResponseBody//為了測(cè)試方便,返回字符串
 public String AdminLogin(
   @RequestParam(value = "username") String username,
   @RequestParam(value = "password") String password) {
  //獲取當(dāng)前用戶 subject
  Subject subject = SecurityUtils.getSubject();
  //封裝用戶的登陸數(shù)據(jù)
  UserToken token = new UserToken(username, Md5.getMd5(password), USER_LOGIN_TYPE);
  try {
   System.out.println("AdminLogin");
   subject.login(token);//執(zhí)行登陸方法
   return null;
  } catch (UnknownAccountException e) {//用戶名不存在
   System.out.println("用戶名錯(cuò)誤");
   return null;
  } catch (IncorrectCredentialsException e) {//密碼錯(cuò)誤
   System.out.println("密碼錯(cuò)誤");
   return null;
  }

Spring Boot 集成Shiro的多realm配置

到此這篇關(guān)于Spring Boot 集成Shiro的多realm實(shí)現(xiàn)以及shiro基本入門的文章就介紹到這了,更多相關(guān)Spring Boot 集成Shiro內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot自動(dòng)重連Redis的實(shí)現(xiàn)方法

    springboot自動(dòng)重連Redis的實(shí)現(xiàn)方法

    由于網(wǎng)絡(luò)或服務(wù)器問(wèn)題,Redis連接可能會(huì)斷開,導(dǎo)致應(yīng)用程序無(wú)法繼續(xù)正常工作,本文主要介紹了springboot自動(dòng)重連Redis的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • IDEA中配置Java反編譯工具javap -c的使用

    IDEA中配置Java反編譯工具javap -c的使用

    本文主要介紹了IDEA中配置Java反編譯工具javap -c的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java設(shè)計(jì)模式七大原則之迪米特法則詳解

    Java設(shè)計(jì)模式七大原則之迪米特法則詳解

    迪米特法則要求一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解,所以迪米特法則又叫做最少知識(shí)原則。本文將為大家詳細(xì)介紹Java設(shè)計(jì)模式七大原則之一的迪米特法則,需要的可以參考一下
    2022-02-02
  • java 根據(jù)身份證號(hào)碼判斷出生日期、性別、年齡的示例

    java 根據(jù)身份證號(hào)碼判斷出生日期、性別、年齡的示例

    這篇文章主要介紹了java 根據(jù)身份證號(hào)碼判斷出生日期、性別、年齡的示例,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-10-10
  • Java判斷字符串回文的代碼實(shí)例

    Java判斷字符串回文的代碼實(shí)例

    在本篇文章里小編給各位整理的是一篇關(guān)于Java判斷字符串回文的代碼實(shí)例內(nèi)容,需要的朋友們可以跟著學(xué)習(xí)參考下。
    2020-02-02
  • JavaAgent的簡(jiǎn)單例子

    JavaAgent的簡(jiǎn)單例子

    這篇文章主要介紹了JavaAgent的簡(jiǎn)單例子,對(duì)JavaAgent感興趣的同學(xué),可以參考下
    2021-04-04
  • 詳解SpringBoot實(shí)現(xiàn)ApplicationEvent事件的監(jiān)聽與發(fā)布

    詳解SpringBoot實(shí)現(xiàn)ApplicationEvent事件的監(jiān)聽與發(fā)布

    這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實(shí)現(xiàn)ApplicationEvent事件的監(jiān)聽與發(fā)布,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-03-03
  • java使用Jdom實(shí)現(xiàn)xml文件寫入操作實(shí)例

    java使用Jdom實(shí)現(xiàn)xml文件寫入操作實(shí)例

    這篇文章主要介紹了java使用Jdom實(shí)現(xiàn)xml文件寫入操作的方法,以完整實(shí)例形式分析了Jdom針對(duì)XML文件寫入操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • Spring中DeferredResult異步處理

    Spring中DeferredResult異步處理

    DeferredResult是Spring中處理異步請(qǐng)求的強(qiáng)大工具,可以幫助改善應(yīng)用程序的性能和用戶體驗(yàn),本文就來(lái)介紹一下Spring中DeferredResult異步處理,感興趣的可以了解一下
    2023-12-12
  • MybatisPlus開啟、關(guān)閉二級(jí)緩存方法

    MybatisPlus開啟、關(guān)閉二級(jí)緩存方法

    本文主要介紹了MybatisPlus開啟、關(guān)閉二級(jí)緩存方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評(píng)論