久久久精品久久久久久96,91国高清在线,欧美日韩高清国产aⅴ一区,在线观看亚洲欧美一区二区三区

<sub id="e1sa3"></sub>

    <pre id="e1sa3"><del id="e1sa3"></del></pre>
    <noscript id="e1sa3"></noscript>

      新疆信息港歡迎您!

      新疆信息港
      新疆信息港 > 科技 >Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整合Shiro實(shí)現(xiàn)用戶登錄認(rèn)證

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整合Shiro實(shí)現(xiàn)用戶登錄認(rèn)證

      2020-08-01 10:46:47
      來源:互聯(lián)網(wǎng)
      閱讀:-

      本文是“Java秒殺系統(tǒng)實(shí)戰(zhàn)系列文章”的第五篇,在本文中,我們將整合權(quán)限認(rèn)證-授權(quán)框架Shiro,實(shí)現(xiàn)用戶的登陸認(rèn)證功能,主要用于:要求用戶在搶購商品或者秒殺商品時(shí),限制用戶進(jìn)行登陸!...


      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整合Shiro實(shí)現(xiàn)用戶登錄認(rèn)證

      本文是“Java秒殺系統(tǒng)實(shí)戰(zhàn)系列文章”的第五篇,在本文中,我們將整合權(quán)限認(rèn)證-授權(quán)框架Shiro,實(shí)現(xiàn)用戶的登陸認(rèn)證功能,主要用于:要求用戶在搶購商品或者秒殺商品時(shí),限制用戶進(jìn)行登陸!并對(duì)于特定的url(比如搶購請(qǐng)求對(duì)應(yīng)的url)進(jìn)行過濾(即當(dāng)用戶訪問指定的url時(shí),需要要求用戶進(jìn)行登陸)。

      對(duì)于Shiro,相信各位小伙伴應(yīng)該聽說過,甚至應(yīng)該也使用過!簡(jiǎn)單而言,它是一個(gè)很好用的用戶身份認(rèn)證、權(quán)限授權(quán)框架,可以實(shí)現(xiàn)用戶登錄認(rèn)證,權(quán)限、資源授權(quán)、會(huì)話管理等功能,在本秒殺系統(tǒng)中,我們將主要采用該框架實(shí)現(xiàn)對(duì)用戶身份的認(rèn)證和用戶的登錄功能。

      值得一提的是,本文介紹的“Shiro實(shí)現(xiàn)用戶登錄認(rèn)證”功能模塊涉及到的數(shù)據(jù)庫表為用戶信息表user,下面進(jìn)入代碼實(shí)戰(zhàn)環(huán)節(jié)。


      01

      首先需要在server模塊加入shiro框架的相關(guān)依賴,其中,版本號(hào)為1.2.6,其完整源代碼如下所示:



      org.apache.shiro
      shiro-ehcache
      ${shiro.version}



      org.apache.shiro
      shiro-core
      ${shiro.version}



      org.apache.shiro
      shiro-web
      ${shiro.version}



      org.apache.shiro
      shiro-spring
      ${shiro.version}

      02

      緊接著是在UserController控制器中開發(fā)用戶前往登錄、用戶登錄以及用戶退出登錄的請(qǐng)求對(duì)應(yīng)的功能方法,其完整的源代碼如下所示:

      @Autowired
      private Environment env;

      //跳到登錄頁
      @RequestMapping(value ={"/to/login","/unauth"})
      public String toLogin(){
      return "login";
      }

      //登錄認(rèn)證
      @RequestMapping(value = "/login",method =RequestMethod.POST)
      public String login(@RequestParam String userName,@RequestParam String password, ModelMap modelMap){
      String errorMsg="";
      try {
      if(!SecurityUtils.getSubject().isAuthenticated()){
      String newPsd=new Md5Hash(password,env.getProperty("shiro.encrypt.password.salt")).toString();
      UsernamePasswordToken token=new UsernamePasswordToken(userName,newPsd);
      SecurityUtils.getSubject().login(token);
      }
      }catch(UnknownAccountException e){
      errorMsg=e.getMessage();
      modelMap.addAttribute("userName",userName);
      }catch(DisabledAccountException e){
      errorMsg=e.getMessage();
      modelMap.addAttribute("userName",userName);
      }catch(IncorrectCredentialsException e){
      errorMsg=e.getMessage();
      modelMap.addAttribute("userName",userName);
      }catch(Exception e){
      errorMsg="用戶登錄異常,請(qǐng)聯(lián)系管理員!";
      e.printStackTrace();
      }
      if(StringUtils.isBlank(errorMsg)){
      return "redirect:/index";
      }else{
      modelMap.addAttribute("errorMsg",errorMsg);
      return "login";
      }
      }

      //退出登錄
      @RequestMapping(value = "/logout")
      public String logout(){
      SecurityUtils.getSubject().logout();
      return"login";
      }

      其中,在匹配用戶的密碼時(shí),我們?cè)谶@里采用的Md5Hash的方法,即MD5加密的方式進(jìn)行匹配(因?yàn)閿?shù)據(jù)庫的user表中用戶的密碼字段存儲(chǔ)的正是采用MD5加密后的加密串)。

      前端頁面login.jsp的內(nèi)容比較簡(jiǎn)單,只需要用戶輸入最基本的用戶名和密碼即可,如下圖所示為該頁面的部分核心源代碼:

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整合Shiro實(shí)現(xiàn)用戶登錄認(rèn)證

      當(dāng)前端提交“用戶登錄”請(qǐng)求時(shí),將以“提交表單”的形式將用戶名、密碼提交到后端UserController控制器對(duì)應(yīng)的登錄方法中,該方法首先會(huì)進(jìn)行最基本的參數(shù)判斷與校驗(yàn),校驗(yàn)通過之后,會(huì)調(diào)用Shiro內(nèi)置的組件SecurityUtils.getSubject().login()方法執(zhí)行登錄操作,其中的登錄操作將主要在 “自定義的Realm的doGetAuthenticationInfo方法”中執(zhí)行。

      03

      接下來是基于Shiro的AuthorizingRealm,開發(fā)自定義的Realm,并實(shí)現(xiàn)其中的用戶登錄認(rèn)證方法,即doGetAuthenticationInfo()方法。其完整的源代碼如下所示:

      /**
      * 用戶自定義的realm-用于shiro的認(rèn)證、授權(quán)
      * @Author:debug (SteadyJack)
      * @Date:2019/7/2 17:55
      **/
      public class CustomRealm extends AuthorizingRealm{
      private static final Logger log= LoggerFactory.getLogger(CustomRealm.class);

      private static final Long sessionKeyTimeOut=3600_000L;
      @Autowired
      private UserMapper userMapper;

      //授權(quán)
      @Override
      protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollectionprincipalCollection) {
      return null;
      }

      //認(rèn)證-登錄
      @Override
      protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationTokenauthenticationToken) throws AuthenticationException {
      UsernamePasswordToken token= (UsernamePasswordToken)authenticationToken;
      String userName=token.getUsername();
      String password=String.valueOf(token.getPassword());
      log.info("當(dāng)前登錄的用戶名={} 密碼={} ",userName,password);

      User user=userMapper.selectByUserName(userName);
      if(user==null){
      throw new UnknownAccountException("用戶名不存在!");
      }
      if(!Objects.equals(1,user.getIsActive().intValue())){
      throw new DisabledAccountException("當(dāng)前用戶已被禁用!");
      }
      if(!user.getPassword().equals(password)){
      throw new IncorrectCredentialsException("用戶名密碼不匹配!");
      }

      SimpleAuthenticationInfo info=newSimpleAuthenticationInfo(user.getUserName(),password,getName());
      setSession("uid",user.getId());
      return info;
      }

      /**
      * 將key與對(duì)應(yīng)的value塞入shiro的session中-最終交給HttpSession進(jìn)行管理(如果是分布式session配置,那么就是交給redis管理)
      * @paramkey
      * @paramvalue
      */
      private void setSession(String key,Object value){
      Session session=SecurityUtils.getSubject().getSession();
      if(session!=null){
      session.setAttribute(key,value);
      session.setTimeout(sessionKeyTimeOut);
      }
      }
      }

      其中,userMapper.selectByUserName(userName);主要用于根據(jù)userName查詢用戶實(shí)體信息,其對(duì)應(yīng)的動(dòng)態(tài)Sql的寫法如下所示:



      值得一提的是,當(dāng)用戶登錄成功時(shí)(即用戶名和密碼的取值跟數(shù)據(jù)庫的user表相匹配),我們會(huì)借助Shiro的Session會(huì)話機(jī)制將當(dāng)前用戶的信息存儲(chǔ)至服務(wù)器會(huì)話中,并緩存一定時(shí)間?。ㄔ谶@里是3600s,即1個(gè)小時(shí))!


      04

      最后是我們需要實(shí)現(xiàn)“用戶在訪問待秒殺商品詳情或者搶購商品或者任何需要進(jìn)行攔截的業(yè)務(wù)請(qǐng)求時(shí),如何自動(dòng)檢測(cè)用戶是否處于登錄的狀態(tài)?如果已經(jīng)登錄,則直接進(jìn)入業(yè)務(wù)請(qǐng)求對(duì)應(yīng)的方法邏輯,否則,需要前往用戶登錄頁要求用戶進(jìn)行登錄”。

      基于這樣的需求,我們需要借助Shiro的組件ShiroFilterFactoryBean 實(shí)現(xiàn)“用戶是否登錄”的判斷,以及借助FilterChainDefinitionMap攔截一些需要授權(quán)的鏈接URL,其完整的源代碼如下所示:

      /**
      * shiro的通用化配置
      * @Author:debug (SteadyJack)
      * @Date:2019/7/2 17:54
      **/
      @Configuration
      public class ShiroConfig {

      @Bean
      public CustomRealm customRealm(){
      return new CustomRealm();
      }

      @Bean
      public SecurityManager securityManager(){
      DefaultWebSecurityManager securityManager=newDefaultWebSecurityManager();
      securityManager.setRealm(customRealm());
      return securityManager;
      }

      @Bean
      publicShiroFilterFactoryBean shiroFilterFactoryBean(){
      ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
      bean.setSecurityManager(securityManager());
      bean.setLoginUrl("/to/login");
      bean.setUnauthorizedUrl("/unauth");
      //對(duì)于一些授權(quán)的鏈接URL進(jìn)行攔截
      Map filterChainDefinitionMap=newHashMap<>();
      filterChainDefinitionMap.put("/to/login","anon");
      filterChainDefinitionMap.put("/**","anon");

      filterChainDefinitionMap.put("/kill/execute","authc");
      filterChainDefinitionMap.put("/item/detail/*","authc");

      bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
      return bean;
      }
      }

      從上述該源代碼中可以看出,Shiro的ShiroFilterFactoryBean組件將會(huì)對(duì) URL=/kill/execute 和 URL=/item/detail/* 的鏈接進(jìn)行攔截,即當(dāng)用戶訪問這些URL時(shí),系統(tǒng)會(huì)要求當(dāng)前的用戶進(jìn)行登錄(前提是用戶還沒登錄的情況下!如果已經(jīng)登錄,則直接略過,進(jìn)入實(shí)際的業(yè)務(wù)模塊?。?/p>

      除此之外,Shiro的ShiroFilterFactoryBean組件還設(shè)定了 “前往登錄頁”和“用戶沒授權(quán)/沒登錄的前提下的調(diào)整頁”的鏈接,分別是 /to/login 和 /unauth!


      05

      至此,整合Shiro框架實(shí)現(xiàn)用戶的登錄認(rèn)證的前后端代碼實(shí)戰(zhàn)已經(jīng)完畢了,將項(xiàng)目/系統(tǒng)運(yùn)行在外置的tomcat服務(wù)器中,打開瀏覽器即可訪問進(jìn)入“待秒殺商品的列表頁”,點(diǎn)擊“詳情”,此時(shí),由于用戶還沒登陸,故而將跳轉(zhuǎn)至用戶登錄頁,如下圖所示:

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整合Shiro實(shí)現(xiàn)用戶登錄認(rèn)證

      輸入用戶名:debug,密碼:123456,點(diǎn)擊“登錄”按鈕,即可登錄成功,并成功進(jìn)入“詳情頁”,如下圖所示:

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整合Shiro實(shí)現(xiàn)用戶登錄認(rèn)證

      登錄成功之后,再回到剛剛上一個(gè)列表頁,即“待秒殺商品的列表頁”,再次點(diǎn)擊“詳情”按鈕,此時(shí)會(huì)直接進(jìn)入“待秒殺商品的詳情頁”,而不會(huì)跳轉(zhuǎn)至“用戶登錄頁”,而且用戶的登錄態(tài)將會(huì)持續(xù)1個(gè)小時(shí)(這是借助Shiro的Session的來實(shí)現(xiàn)的)。

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整合Shiro實(shí)現(xiàn)用戶登錄認(rèn)證

      Debug有話說

      1、目前,這一秒殺系統(tǒng)的整體構(gòu)建與代碼實(shí)戰(zhàn)已經(jīng)全部完成了,完整的源代碼數(shù)據(jù)庫地址可以來這里下載:https://gitee.com/steadyjack/SpringBoot-SecondKill

      記得Fork跟Star?。。。?/p>

      2、由于相應(yīng)的博客的更新可能并不會(huì)很快,故而如果有想要快速入門以及實(shí)戰(zhàn)整套系統(tǒng)的,可以考慮聯(lián)系Debug獲取這一“Java秒殺系統(tǒng)”的完整視頻教程(課程是收費(fèi)的?。?,當(dāng)然,大家也可以點(diǎn)擊下面這個(gè)鏈接:https://gitee.com/steadyjack/SpringBoot-SecondKill

      聯(lián)系Debug或者加入相應(yīng)的技術(shù)交流群進(jìn)行交流!

      3、實(shí)戰(zhàn)期間有任何問題都可以留言或者與Debug聯(lián)系、交流。

      推薦閱讀

      Java商城秒殺系統(tǒng)的設(shè)計(jì)與實(shí)戰(zhàn)教程(SpringBoot版)

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-構(gòu)建SpringBoot多模塊項(xiàng)目

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-整體業(yè)務(wù)流程介紹與數(shù)據(jù)庫設(shè)計(jì)

      Java秒殺系統(tǒng)實(shí)戰(zhàn)系列-待秒殺商品列表與詳情功能開發(fā)

      推薦閱讀:小黑板

      免責(zé)聲明:本文僅代表企業(yè)觀點(diǎn),與新疆信息港無關(guān)。其原創(chuàng)性以及文中陳述文字和內(nèi)容未經(jīng)本站證實(shí),對(duì)本文以及其中全部或者部分內(nèi)容、文字的真實(shí)性、完整性、及時(shí)性本站不作任何保證或承諾,請(qǐng)讀者僅作參考,并請(qǐng)自行核實(shí)相關(guān)內(nèi)容。
      熱門圖片
      熱門搜索