欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot 整合 Shiro 密碼登錄與郵件驗證碼登錄功能(多 Realm 認證)

 更新時間:2021年02月26日 11:05:06   作者:風(fēng)青宇  
這篇文章主要介紹了SpringBoot 整合 Shiro 密碼登錄與郵件驗證碼登錄(多 Realm 認證),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

導(dǎo)入依賴(pom.xml)

 <!--整合Shiro安全框架-->
  <dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.4.0</version>
  </dependency>
  <!--集成jwt實現(xiàn)token認證-->
  <dependency>
   <groupId>com.auth0</groupId>
   <artifactId>java-jwt</artifactId>
   <version>3.2.0</version>
  </dependency>

在 SpringBoot 項目配置 config 包下創(chuàng)建 ShiroConfig 配置類

@Configuration
public class ShiroConfig {

 /**
  * ShiroFilterFactoryBean
  * <p>
  * anon:無需認證就可以訪問
  * authc:必須認證才能訪問
  * user:必須擁有 記住我 功能才能用
  * perms:擁有對某個資源的權(quán)限能訪問
  * role:擁有某個角色權(quán)限能訪問
  */
 @Bean
 public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
  ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
  // 設(shè)置安全管理器
  factoryBean.setSecurityManager(defaultWebSecurityManager);
  // 添加shiro的內(nèi)置過濾器
  Map<String, String> filterMap = new LinkedHashMap<>();
  // 放行不需要權(quán)限認證的接口
  // 網(wǎng)站首頁
  filterMap.put("/", "anon");
  filterMap.put("/index", "anon");
  filterMap.put("/index.html", "anon");
  // 不驗證跳轉(zhuǎn)接口
  filterMap.put("/into/**", "anon");

  // 需要權(quán)限認證的接口
  // 驗證跳轉(zhuǎn)接口
  filterMap.put("/verifyInto/**", "authc");
  
  factoryBean.setFilterChainDefinitionMap(filterMap);

  // 訪問沒有授權(quán)的資源
  factoryBean.setLoginUrl("redirect:/into/login");
  // 設(shè)置無權(quán)限時跳轉(zhuǎn)的url
  factoryBean.setUnauthorizedUrl("redirect:/into/login");

  return factoryBean;
 }

 /**
  * 管理shiro的生命周期
  */
 @Bean("lifecycleBeanPostProcessor")
 public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
  return new LifecycleBeanPostProcessor();
 }

 /**
  * 注入 密碼登錄CustomRealm
  */
 @Bean
 @DependsOn("lifecycleBeanPostProcessor")
 public UserPasswordRealm userPasswordRealm() {
  return new UserPasswordRealm();
 }

 /**
  * 注入 郵箱驗證登錄EmailRealm
  */
 @Bean
 @DependsOn("lifecycleBeanPostProcessor")
 public UserEmailRealm userEmailRealm() {
  return new UserEmailRealm();
 }

 /**
  * 默認安全管理器
  */
 @Bean
 public DefaultWebSecurityManager securityManager(UserPasswordRealm userPasswordRealm, UserEmailRealm userEmailRealm, AbstractAuthenticator abstractAuthenticator) {
  DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
  List<Realm> realms = new ArrayList<>();
  realms.add(userPasswordRealm);
  realms.add(userEmailRealm);
  defaultWebSecurityManager.setRealms(realms);
  // 記住我
  defaultWebSecurityManager.setRememberMeManager(cookieRememberMeManager());
  defaultWebSecurityManager.setAuthenticator(abstractAuthenticator);
  return defaultWebSecurityManager;
 }

 /**
  * 認證器 把我們的自定義驗證加入到認證器中
  */
 @Bean
 public AbstractAuthenticator abstractAuthenticator(UserPasswordRealm userPasswordRealm, UserEmailRealm userEmailRealm) {
  // 自定義模塊化認證器,用于解決多realm拋出異常問題
  //開始沒用自定義異常問題,發(fā)現(xiàn)不管是賬號密碼錯誤還是什么錯誤
  //shiro只會拋出一個AuthenticationException異常
  ModularRealmAuthenticator authenticator = new MyCustomModularRealmAuthenticator();
  // 認證策略:AtLeastOneSuccessfulStrategy(默認),AllSuccessfulStrategy,F(xiàn)irstSuccessfulStrategy
  authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
  // 加入realms
  List<Realm> realms = new ArrayList<>();
  realms.add(userPasswordRealm);
  realms.add(userEmailRealm);
  authenticator.setRealms(realms);
  return authenticator;
 }

 /**
  * 加入shiro注解 代理生成器 切面
  */
 @Bean
 @DependsOn({"lifecycleBeanPostProcessor"})
 public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
  DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
  advisorAutoProxyCreator.setProxyTargetClass(true);
  return advisorAutoProxyCreator;
 }

 /**
  * 加入shiro注解 切點
  */
 @Bean
 public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
  AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
  authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
  return authorizationAttributeSourceAdvisor;
 }

 /**
  * 設(shè)置cookie 記住我生成cookie
  */
 @Bean
 public CookieRememberMeManager cookieRememberMeManager() {
  CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
  cookieRememberMeManager.setCookie(rememberMeCookie());
  return cookieRememberMeManager;
 }

 /**
  * 設(shè)置cookie有效時間
  */
 @Bean
 public SimpleCookie rememberMeCookie() {
  /*這個參數(shù)是cookie的名稱,對應(yīng)前端頁面的checkbox的name=remremberMe*/
  SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
  /*cookie的有效時間為30天,單位秒*/
  simpleCookie.setMaxAge(259200);
  return simpleCookie;
 }

}

創(chuàng)建自定義驗證器 MyCustomModularRealmAuthenticator 類

public class MyCustomModularRealmAuthenticator extends ModularRealmAuthenticator {

 @Override
 protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
  AuthenticationStrategy authenticationStrategy = this.getAuthenticationStrategy();
  AuthenticationInfo authenticationInfo = authenticationStrategy.beforeAllAttempts(realms, token);

  Iterator var5 = realms.iterator();
  while (var5.hasNext()) {
   Realm realm = (Realm) var5.next();
   authenticationInfo = authenticationStrategy.beforeAttempt(realm, token, authenticationInfo);
   if (realm.supports(token)) {

    AuthenticationInfo info = null;
    Throwable t = null;

    info = realm.getAuthenticationInfo(token);

    authenticationInfo = authenticationStrategy.afterAttempt(realm, token, info, authenticationInfo, t);
   }
  }
  authenticationInfo = authenticationStrategy.afterAllAttempts(token, authenticationInfo);
  return authenticationInfo;
 }
}

創(chuàng)建密碼登錄時驗證授權(quán) UserPasswordRealm 類

@Component
public class UserPasswordRealm extends AuthorizingRealm {

 // 注入用戶業(yè)務(wù)
 @Autowired
 private UserMapper userMapper;

 /**
  * 授權(quán)
  */
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  System.out.println("————密碼授權(quán)————doGetAuthorizationInfo————");

  return null;
 }

 /**
  * 認證
  */
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  System.out.println("————密碼認證————doGetAuthenticationInfo————");

  UsernamePasswordToken userToken = (UsernamePasswordToken) token;
  // 連接數(shù)據(jù)庫 查詢用戶數(shù)據(jù)
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  wrapper.eq("user_name", userToken.getUsername());
  User user = userMapper.selectOne(wrapper);
  // 驗證用戶
  if (user == null) {
   throw new UnknownAccountException();
  }
  return new SimpleAuthenticationInfo("", user.getUserPassword(), "");
 }

 /**
  * 用來判斷是否使用當前的 realm
  *
  * @param var1 傳入的token
  * @return true就使用,false就不使用
  */
 @Override
 public boolean supports(AuthenticationToken var1) {
  return var1 instanceof UsernamePasswordToken;
 }

}

創(chuàng)建郵件驗證碼登錄時驗證授權(quán)UserEmailRealm

@Component
public class UserEmailRealm extends AuthorizingRealm {

 // 注入用戶業(yè)務(wù)
 @Autowired
 UserService userService;

 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  System.out.println("————郵箱登錄授權(quán)————doGetAuthorizationInfo————");
  return null;
 }

 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  System.out.println("————郵箱登錄認證————doGetAuthenticationInfo————");
  UserEmailToken userEmailToken = (UserEmailToken) token;
  String userEmail = (String) userEmailToken.getPrincipal();
  // 連接數(shù)據(jù)庫 查詢用戶數(shù)據(jù)
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  wrapper.eq("user_email", userEmail);
  User user = userService.getOne(wrapper);
  //因為沒有密碼,并且驗證碼在之前就驗證了
  if (user == null) {
   throw new UnknownAccountException();
  }
  return new SimpleAuthenticationInfo("", userEmail, "");
 }

 /**
  * 用來判斷是否使用當前的 realm
  *
  * @param var1 傳入的token
  * @return true就使用,false就不使用
  */
 @Override
 public boolean supports(AuthenticationToken var1) {
  return var1 instanceof UserEmailToken;
 }
}

創(chuàng)建郵件驗證碼登錄驗證通過生成令牌的 UserEmailToken 類(密碼登錄時使用shiro默認的 UsernamePasswordToken 令牌)

@Data // 使用lombok 生成get方法、set方法
public class UserEmailToken implements HostAuthenticationToken, RememberMeAuthenticationToken {

 private String userEmail;
 private boolean rememberMe;
 private String host;

 public UserEmailToken() {
  this.rememberMe = false;
 }

 public UserEmailToken(String userEmail) {
  this(userEmail, false, null);
 }

 public UserEmailToken(String userEmail, boolean rememberMe) {
  this(userEmail, rememberMe, null);
 }

 public UserEmailToken(String userEmail, boolean rememberMe, String host) {
  this.userEmail = userEmail;
  this.rememberMe = rememberMe;
  this.host = host;
 }

 @Override
 public String getHost() {
  return host;
 }

 @Override
 public boolean isRememberMe() {
  return rememberMe;
 }

 /**
  * 重寫getPrincipal方法
  */
 @Override
 public Object getPrincipal() {
  return userEmail;
 }

 /**
  * 重寫getCredentials方法
  */
 @Override
 public Object getCredentials() {
  return userEmail;
 }
}

創(chuàng)建密碼鹽值加密 MDPasswordUtil 工具類

public class MDPasswordUtil {

 public String getMDPasswordUtil(String userName, String userPassword) {
  String hashAlgorithmName = "MD5"; // 加密方式:md5加密
  Object credentials = userPassword; // 密碼
  Object salt = ByteSource.Util.bytes(userName); // 鹽
  int hashIterations = 512; // 加密次數(shù)
  Object result = new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
  return result.toString();
 }
}

控制層用戶密碼登錄

// 用戶密碼登錄
 @PostMapping("/passwordLogin")
 public String userLogin(@RequestParam("userName") String userName,
       @RequestParam("userPassword") String userPassword,
       HttpSession session, Model model) {
  // 獲取當前的用戶
  Subject subject = SecurityUtils.getSubject();
  // 對密碼進行MD5鹽值加密
  String md5Password = new MDPasswordUtil().getMDPasswordUtil(userName, userPassword);
  // 封裝用戶的登錄數(shù)據(jù)
  UsernamePasswordToken token = new UsernamePasswordToken(userName, md5Password);
  //rememberme記住我
  token.setRememberMe(true);
  try {
   // 登錄,驗證,保存令牌
   subject.login(token);

   //查詢登錄信息
   QueryWrapper<User> wrapper = new QueryWrapper<>();
   wrapper.eq("user_name", userName);
   User user = userService.getOne(wrapper);
   //保存登錄用戶信息
   session.setAttribute(user.getUserId().toString(), user);

   return "admin";
  } catch (UnknownAccountException e) {
   model.addAttribute("userError", "用戶名錯誤!請重新輸入。");
   return "login";
  } catch (IncorrectCredentialsException ice) {
   model.addAttribute("pwError", "密碼錯誤!請重新輸入。");
   return "login";
  }
 }

控制層用戶郵件驗證碼密碼登錄

// 用戶郵箱登錄
 @PostMapping("/emailLogin")
 public String emailLogin(@RequestParam("userEmail") String userEmail,
        @RequestParam("emailCode") String emailCode,
        HttpSession session, Model model) {
  // 根據(jù)userEmail從session中取出發(fā)送的驗證碼
  String sendEmailCode = (String) session.getAttribute(userEmail);
  // 比對驗證碼
  if (StringUtils.isNoneBlank(sendEmailCode) && sendEmailCode.equals(emailCode)) {
   try {
    UserEmailToken token = new UserEmailToken(userEmail);
    //rememberme記住我
    token.setRememberMe(true);
    // 登錄,驗證,保存令牌
    Subject subject = SecurityUtils.getSubject();
    subject.login(token);

    //查詢登錄信息
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("user_email", userEmail);
    User user = userService.getOne(wrapper);
    //保存登錄用戶信息
    session.setAttribute(user.getUserId().toString(), user);

    // 銷毀驗證碼
    session.removeAttribute(emailCode);

    return "admin";
   } catch (Exception e) {
    model.addAttribute("error", "驗證碼錯誤!請重新輸入。");
    return "login";
   }
  } else {
   return "login";
  }
 }

SpringBoot 整合 Shiro 密碼登錄與郵件驗證碼登錄(多 Realm 認證)就可以了 (有點多,哈哈哈)

推薦大神:狂神說Java

到此這篇關(guān)于SpringBoot 整合 Shiro 密碼登錄與郵件驗證碼登錄(多 Realm 認證)的文章就介紹到這了,更多相關(guān)SpringBoot 整合 Shiro登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?spring?boot實現(xiàn)批量刪除功能詳細示例

    Java?spring?boot實現(xiàn)批量刪除功能詳細示例

    這篇文章主要給大家介紹了關(guān)于Java?spring?boot實現(xiàn)批量刪除功能的相關(guān)資料,文中通過代碼以及圖文將實現(xiàn)的方法介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2023-08-08
  • Mybatis 實現(xiàn)動態(tài)組裝查詢條件,仿SQL模式

    Mybatis 實現(xiàn)動態(tài)組裝查詢條件,仿SQL模式

    這篇文章主要介紹了Mybatis 實現(xiàn)動態(tài)組裝查詢條件,仿SQL模式的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • IDEA一致卡在build時間過長問題解決

    IDEA一致卡在build時間過長問題解決

    有很多小伙伴在起項目的時候巨慢,特別影響開發(fā)效率,本文主要介紹了IDEA一致卡在build時間過長問題解決,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • 使用maven生成可執(zhí)行的jar包的方法

    使用maven生成可執(zhí)行的jar包的方法

    這篇文章主要介紹了使用maven生成可執(zhí)行的jar包的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • 帶你詳細了解Java值傳遞和引用傳遞

    帶你詳細了解Java值傳遞和引用傳遞

    這篇文章主要介紹了帶你詳細了解Java值傳遞和引用傳遞,文中有非常詳細的代碼示例,對正在學(xué)習(xí)java的小伙伴們有一定的幫助,需要的朋友可以參考下
    2021-04-04
  • Java設(shè)計模式之創(chuàng)建者模式簡介

    Java設(shè)計模式之創(chuàng)建者模式簡介

    這篇文章主要介紹了Java設(shè)計模式之創(chuàng)建者模式,需要的朋友可以參考下
    2014-07-07
  • redis客戶端Jedis使用小結(jié)

    redis客戶端Jedis使用小結(jié)

    Jedis是Redis的一款Java語言的開源客戶端連接工具,本文主要介紹了redis客戶端Jedis使用,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • spring啟動錯誤Singleton bean creation not allowed while the singletons of this factory are indestruction

    spring啟動錯誤Singleton bean creation not al

    本文主要介紹了spring啟動錯誤Singleton bean creation not allowed while the singletons of this factory are indestruction,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • SpringBoot集成Redisson操作Redis的實現(xiàn)方法

    SpringBoot集成Redisson操作Redis的實現(xiàn)方法

    Redisson是一個用于Java的Redis客戶端,它提供了在分布式環(huán)境下操作Redis數(shù)據(jù)庫的簡單、高效的方式,本文主要介紹了SpringBoot集成Redisson操作Redis的實現(xiàn)方法,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • uploadify上傳及后臺文件合法性驗證的代碼解析

    uploadify上傳及后臺文件合法性驗證的代碼解析

    這篇文章主要介紹了uploadify上傳及后臺文件合法性驗證的代碼解析,整段代碼分為后臺上傳方法,文件合法性驗證類,前端上傳js,非常不錯具有參考借鑒價值,需要的朋友可以參考下
    2016-11-11

最新評論