Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产日韩精品视频,国产超a特工片免费完整版电影 ,国产精品精品

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          在asp.net core 中控制訪問權限的方法

          在asp.net core 中控制訪問權限的方法



          ntro#

          由于項目需要,需要在基于 asp.net mvc 的 Web 項目框架中做權限的控制,于是才有了這個權限控制組件,最初只是支持 netframework,后來 dotnetcore 2.0 發布了之后添加了對 asp.net core 的支持,在 dotnetcore 3.0 發布之后也增加了對 asp.net core 3.0 的支持(1.9.0及之后版本),目前對于 asp.net core 支持的更多一些,asp.net core 可以使用 TagHelper 來控制頁面上元素的權限訪問,也可以通過 Policy 來控制權限訪問,同時支持通過中間件也可以實現對靜態資源的訪問。

          安裝 AccessControlHelper nuget 包#

          安裝 nuget 包 WeihanLi.AspNetMvc.AccessControlHelper

          Copydotnet add package WeihanLi.AspNetMvc.AccessControlHelper
          

          實現自己的訪問策略#

          資源訪問策略/API訪問策略#

          以下代碼定義了一個簡單的訪問策略,需要登錄且擁有 Admin 角色,可以根據自己需要調整優化

          Copypublic class AdminPermissionRequireStrategy : IResourceAccessStrategy
          {
              private readonly IHttpContextAccessor _accessor;
          
              public AdminPermissionRequireStrategy(IHttpContextAccessor accessor)
              {
                  _accessor=accessor;
              }
          
              public bool IsCanAccess(string accessKey)
              {
                  var user=_accessor.HttpContext.User;
                  return user.Identity.IsAuthenticated && user.IsInRole("Admin");
              }
          
              public IActionResult DisallowedCommonResult=> new ContentResult
              {
                  Content="No Permission",
                  ContentType="text/plain",
                  StatusCode=403
              };
          
              public IActionResult DisallowedAjaxResult=> new JsonResult(new JsonResultModel
              {
                  ErrorMsg="No Permission",
                  Status=JsonResultStatus.NoPermission
              });
          }
          

          頁面元素訪問策略#

          定義頁面元素/控件訪問策略:

          Copypublic class AdminOnlyControlAccessStrategy : IControlAccessStrategy
          {
              private readonly IHttpContextAccessor _accessor;
          
              public AdminOnlyControlAccessStrategy(IHttpContextAccessor httpContextAccessor)=> _accessor=httpContextAccessor;
          
              public bool IsControlCanAccess(string accessKey)
              {
                  if ("Never".Equals(accessKey, System.StringComparison.OrdinalIgnoreCase))
                  {
                      return false;
                  }
                  var user=_accessor.HttpContext.User;
                  return user.Identity.IsAuthenticated && user.IsInRole("Admin");
              }
          }
          

          服務注冊配置#

          在 Startup 里注冊服務:

          Copyservices.AddAccessControlHelper()
              .AddResourceAccessStrategy<AdminPermissionRequireStrategy>()
              .AddControlAccessStrategy<AdminOnlyControlAccessStrategy>()
              ;
          

          如果你只是 web api ,不涉及到頁面元素的權限控制可以只注冊 ResourceAccessStrategy

          Copyservices.AddAccessControlHelper()
          .AddResourceAccessStrategy<AdminPermissionRequireStrategy>();
          

          默認訪問策略的生命周期是單例的,如果需要注冊為Scoped,可以指定默認的生命周期

          Copyservices.AddAccessControlHelper()
          .AddResourceAccessStrategy<AdminPermissionRequireStrategy>(ServiceLifetime.Scoped);
          

          API/資源的權限控制#

          對于 asp.net core 應用推薦使用 Policy 來控制權限的訪問,可以在需要權限控制的 Action 或者 Controller 上設置 [Authorize("AccessControl")] 或者 [Authorize(AccessControlHelperConstants.PolicyName)]

          Copy[Authorize(AccessControlHelperConstants.PolicyName)]
          public class SystemSettingsController : AdminBaseController
          {
              // ...
          }
          
          Copy[Authorize(AccessControlHelperConstants.PolicyName)]
          public ActionResult UserList()
          {
              return View();
          }
          

          頁面元素的權限控制#

          引用 TagHelper#

          在 Views 目錄下的 _ViewImports.cshtml 文件中導入 AccessControlHelper 的 TagHelper

          Copy@using ActivityReservation
          @using WeihanLi.AspNetMvc.AccessControlHelper
          @using WeihanLi.AspNetMvc.MvcSimplePager
          
          @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
          @addTagHelper *, WeihanLi.AspNetMvc.AccessControlHelper
          

          頁面元素配置#

          在需要權限控制的元素上增加 asp-access 的 attribute 就可以了,如果需要 access-key 通過 asp-access-key 來配置

          Copy<ul class="list-group" asp-access asp-access-key="AdminOnly">
              <li role="separator" class="list-unstyled">
                  <br />
              </li>
              <li class="list-group-item">@Html.ActionLink("用戶管理", "UserList", "Account")</li>
          
              <li class="list-group-item">@Html.ActionLink("操作日志查看", "Index", "OperationLog")</li>
              <li class="list-group-item">@Html.ActionLink("系統設置管理", "Index", "SystemSettings")</li>
              <li class="list-group-item">
                  @Html.ActionLink("微信設置管理", "Index", new {
                  controller="Config",
                  area="Wechat"
              })
              </li>
          </ul>
          

          這樣就可以了,有權限訪問的時候才會正常渲染,沒有權限訪問的時候,這一段 ul 并不會渲染輸出,在客戶端瀏覽器查看源代碼也不會看到對應的代碼

          ormMaking介紹

          FormMaking表單設計器是一款與行業無關的通用表單設計器前端解決方案,表單設計器包含設計器(MakingForm)和生成器(GenerateForm)兩個模塊,設計器主要負責表單的動態設計,可以通過拖拽的形式設計生成表單頁面,生成器則負責對表單頁面的渲染和數據的回寫。

          如果你對FormMaking不太了解可能會把FormMaking當成是單純頁面設計器,只為了減少重復的表單,稍微有點經驗的前端開發,通過簡單的Copy Paste就能很快做出一個固定的表單頁面。而FormMaking做的是一整套與表單相關的前端方案,包含了表單的動態設計,表單渲染,數據回寫,數據校驗,事件支持,css自定義,動作面板等豐富的功能,而這些所有的功能只需要一個import 命令將MakingFormGenerateForm引入到項目中,你的項目就可以擁有這些功能。

          FormMaking新功能 自定義字段高級用法

          FormMaking基礎功能可以看之前都介紹。

          本文我們將介紹如何使用 FormMaking 來引入自己的高級組件,并可以通過設計器進行配置,處理事件等操作

          封裝分頁數據表格組件

          我們將封裝 一個分頁數據表格組件,組件采用 ElementPlus TableV2

          <template>
            <div>
              <div style="height: 400px">
                <el-auto-resizer>
                  <template #default="{ height, width }">
                    <el-table-v2
                      :columns="columns"
                      :data="data"
                      :width="width"
                      :height="height"
                      fixed
                    />
                  </template>
                </el-auto-resizer>
              </div>
              <el-pagination 
                background 
                layout="prev, pager, next" 
                :total="1000" 
                v-model:current-page="currentPage"
                @current-change="loadPageData"
              />
            </div>
          </template>
          
          <script setup>
          import { onMounted, ref, watch } from 'vue'
          
          const props=defineProps({
            modelValue:  {
              type: Array,
              default: ()=> []
            },
            columns: {
              type: Array,
              default: ()=> []
            }
          })
          
          const emit=defineEmits(['on-load'])
          
          const data=ref(props.modelValue)
          
          const currentPage=ref(1)
          
          const loadPageData=(index)=> {
            // 通過 emit,可以將事件拋出到設計器中進行配置
            emit('on-load', index)
          }
          
          onMounted(()=> {
            emit('on-load', currentPage.value)
          })
          
          watch(()=> props.modelValue, (val)=> {
            data.value=val
          })
          </script>
          


          引入到設計器

          注冊組件

          首先應該在自己項目中進行組件的注冊。

          import CustomPaginationTable from 'PaginationTable.vue'
          
          app.use(FormMakingV3, {
            components: [{
              name: 'custom-pagination-table',
              component: CustomPaginationTable // 自定義組件
            }]
          })

          也可以使用Vue.component 進行組件的注冊

          app.component('custom-pagination-table', CustomPaginationTable)

          設計器配置

          <template>
          <fm-making-form
            :custom-fields="customFields"
          >
            </fm-making-form>
          </template>
          
          <script>
            export default {
              data() {
                return {
                  customFields: [
                    {
                      name: '分頁數據列表',
                      el: 'custom-pagination-table',
                      options: {
                        defaultValue: [],
                        labelWidth: 0,
                        isLabelWidth: false,
                        hidden: false,
                        dataBind: true,
                        validator: '',
                        extendProps: {
                          columns: [] // 用于配置表格的列
                        }
                      },
                      events: {
                        onLoad: '' // 定義設計器可以配置的事件,處理組件 emit 的事件
                      }
                    }
                  ]
                }
              }
            }
          </script>

          然后在自定義字段中就展示出來了


          設計器界面

          配置組件表格

          表格列配置

          在字段屬性中對擴展屬性配置 進行設置



          數據加載

          數據加載的 on-load事件,我們在自定義組件中通過emit拋出到設計器中進行配置,在字段屬性-動作設置中添加onLoad事件配置如下:

          效果展示

          我們來查看下最后的效果

          效果圖

          更多關于FormMaking詳情可移步:

          可視化低代碼表單設計器 - FormMaking

          寶頁面比較復雜,含有各種請求參數和加密參數,如果直接請求或者分析Ajax將會非常繁瑣。Selenium是一個自動化測試工具,可以驅動瀏覽器去完成各種工作,比如模擬點擊、輸入和下拉等多種功能,這樣我們只需關心操作,不需要關心后臺發生了怎么樣的請求下面對具體操作步驟進行詳述

          實現流程

          1.搜索關鍵字:利用Selenium驅動瀏覽器搜索關鍵字,得到查詢后的商品列表

          2.分析頁碼并翻頁:得到商品頁碼數,模擬翻頁,得到后續頁面的商品列表

          3.分析提取商品內容:利用PyQuery分析源碼,解析得到商品列表

          4.存儲至MongoDB:將商品列表信息存儲到數據庫MongoDB

          具體實現

          1.首先需要聲明一個browser用來操作,我的是chrome。這里的wait是在后面的判斷元素是否出現時使用,第二個參數為等待最長時間,超過該值則拋出異常

          #創建一個瀏覽器對象
          browser=webdriver.Chrome()
          #十秒內尋找元素失敗,將報出TimeoutException異常
          wait=WebDriverWait(browser, 10)
          

          2.聲明好之后就需要進行打開網頁、進行搜索的操作

          def search():
           """
           作用:通過關鍵字搜索得到搜索內容第一頁產品信息,并返回搜索內容共計頁碼
           """
           print('正在搜索')
           try: 
           browser.get('https://www.taobao.com')
           print(browser.page_source)
           
           # 獲取input輸入框對象
           input=wait.until(
           EC.presence_of_element_located((By.CSS_SELECTOR, "#q")) 
           )#
           # 獲取button提交對象
           submit=wait.until(
           EC.element_to_be_clickable(
           (By.CSS_SELECTOR, "#J_TSearchForm > div.search-button > button")
           )
           )
           # KEYWORD是config.py文件中定義的搜索關鍵字,可修改
           input.send_keys(KEYWORD)
           # 點擊button提交按鈕
           submit.click()
           # 通過CSS_SELECTOR選擇器獲取total頁碼
           total_page=wait.until(
           EC.presence_of_element_located(
           (By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.total")
           ) 
           )
           # 解析頁面內容,并將數據保存至MongoDB中
           get_products()
           return total_page.text
           except TimeoutException:
           # 出現超時訪問就重新調用一次search
           return search()
          

          3.第一個頁面操作之后,我們需要進行翻頁操作,如下:

          def next_page(page_number):
           """
           作用:作人為翻頁功能,并得到該頁產品信息
           page_number:循環的頁碼,將頁碼寫入input框中
           """
           print('正在翻頁', page_number)
           
           try:
           # 獲取input輸入框對象
           input=wait.until(
           EC.presence_of_element_located(
           (By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input")
           ) 
           )
           # 獲取button提交對象
           submit=wait.until(
           EC.element_to_be_clickable(
           (By.CSS_SELECTOR, "div > div > div > div.form > span.btn.J_Submit")
           )
           )
           # 將input框清空
           input.clear()
           # 向input框中輸入頁碼
           input.send_keys(page_number)
           # 點擊button提交按鈕
           submit.click()
           wait.until(
           # 驗證輸入框內的頁碼是否為當前高亮頁碼,如果是,則繼續執行
           # text參數是否在該span元素內,此處需要注意text的參數位置
           EC.text_to_be_present_in_element(
           (By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > ul > li.item.active > span'), str(page_number)
           )
           )
           
           # 獲取產品信息并保存至MongoDB
           get_products()
           except TimeoutException:
           # 超時異常,則繼續解析該頁
           next_page(page_number)
          

          4.寫完搜索操作和翻頁操作后,我們需要完成對每個頁面的商品信息獲取功能

          def get_products():
           """
           作用:通過頁面源代碼,將產品信息保存至MongoDB中
           """
           # 通過CSS_SELECTOR選擇器,驗證頁面中是否存在產品對象
           wait.until(
           EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-itemlist .items .item"))
           )
           # 拿到頁面源碼
           html=browser.page_source
           
           # 通過pyquery找到產品對象
           doc=pq(html)
           items=doc('#mainsrp-itemlist .items .item').items()
           # 遍歷每個產品對象,組建數據內容
           for item in items:
           product={
           'image': item.find('.pic .img').attr('src'),
           'price': item.find('.price').text(),
           'deal': item.find('.deal-cnt').text()[:-3],
           'title': item.find('.title').text(),
           'shop': item.find('.shop').text(),
           'location': item.find('.location').text()
           }
           # print(product)
           # 將組建好的每個產品信息保存至MongoDB
           save_to_mongo(product)
          

          5.獲取信息之后則需要對信息進行存儲,將數據庫關鍵參數定義在config.py文件中

          #!/usr/bin/env python
          # coding=utf-8
          # 本地的數據庫
          MONGO_URL='localhost'
          # 數據庫的名稱
          MONGO_DB='taobao'
          # 數據庫的表名
          MONGO_TABLE='products'
          

          6.將組建好的每個產品信息保存至MongoDB

          # 創建一個MongoDB對象
          client=pymongo.MongoClient(MONGO_URL)
          # 創建一個數據庫,注意是[]而不是()
          db=client[MONGO_DB]
          def save_to_mongo(result):
           """
           作用:將信息保存至MongoDB中
           """
           try:
           if db[MONGO_TABLE].insert(result):
           print('Successfully save to MongoDB', result)
           
           except Exception:
           print('Failed save to MongoDB', result)
          

          7.爬取調度器

          def TbMeishi_Spider():
           """
           作用:淘寶美食爬取調度器
           """
           try:
           total_page=search()
           # 通過正則將search返回的total頁碼內容解析成數字形式
           pattern=re.compile('(\d+)')
           total_page=int(pattern.search(total_page).group(1))
           # print(total_page)
           # 遍歷頁碼,傳入next_page函數中,做整站爬取
           for i in range(2, total_page + 1):
           next_page(i)
           
           except Exception:
           print('有錯誤產生...')
           
           finally:
           browser.close()
          

          8.代碼完成到這里已經可以結束了,但是使用Selenium模擬會發現每次運行程序都會打開一個瀏覽器,然后自動操作,可以最直接地觀察到代碼的運行,但是假如不想彈出瀏覽器的話,可以使用PhantomJS來實現一個無界面的webkit瀏覽器。雖然沒有界面,但dom渲染、js運行、網絡訪問、canvas/svg繪制等功能都很完備,在頁面抓取、頁面輸出、自動化測試等方面有廣泛的應用。下載PhantomJS地址:http://phantomjs.org/download.html,下載完成后解壓縮,將PhantomJS添加到環境變量中即可

          在config.py文件中加上

          # 關閉load-images的功能,加快運行速度,默認開啟,開啟disk-cache緩存,默認關閉
          SERVICE_ARGS=['--load-images=false', '--disk-cache=true']
          # 無界面瀏覽器,將browser改為
          browser=webdriver.PhantomJS(service_args=SERVICE_ARGS)
          # 設置PlantomJS的窗口大小,可能會影響內容下載
          browser.set_window_size(1400, 900)
          

          總結思考

          1.目標網址不匹配

          一開始使用顯示等待訪問,通過CSS_SELECTOR的id選擇器找到網頁元素,可最后程序都執行異常,每次都是TimeoutExceptions的異常錯誤。經過反復排查,才發現淘寶網有很多個站點

          我在程序中使用的是:http://www.taobao.com

          但是在進行網頁分析的時候隨意用百度搜了一個淘寶站點,它的站點是:https://uland.taobao.com/sem/tbsearch

          兩個站點地址不一樣,網頁元素也不一樣,自己竟然會犯這種錯誤,應牢記,正確的選擇元素應該是下面這幾行

          from selenium.webdriver.common.by import By
          from selenium.webdriver.support.ui import WebDriverWait
          from selenium.webdriver.support import expected_conditions as EC
          input=WebDriverWait(browser, 10).until(
           EC.presence_of_element_located((By.ID, 'q'))
          )
          button=WebDriverWait(browser, 10).until(
           EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search'))
          )
          

          2.text參數是否在該span元素內,此處需要注意text的參數位置

          # 驗證text參數是否與選擇器選擇的元素文本內容一致
          text_to_be_present_in_element(locator, text_)
          

          3.完整源碼地址:https://github.com/XiaoFei-97/TbMeishi_Spider\


          主站蜘蛛池模板: 国产精品女同一区二区| 久久国产高清一区二区三区| 亚洲.国产.欧美一区二区三区 | 亚洲视频一区二区在线观看| 国产小仙女视频一区二区三区| 无码人妻AV免费一区二区三区| 亚洲国产精品第一区二区三区| 中文字幕人妻AV一区二区| 亚洲国产精品无码久久一区二区 | 久久国产精品无码一区二区三区 | 三上悠亚国产精品一区| 无码国产精品一区二区免费I6| 日本中文字幕一区二区有码在线| 国产另类ts人妖一区二区三区| 国产在线观看一区二区三区四区| 竹菊影视欧美日韩一区二区三区四区五区| 精品无码一区二区三区爱欲| 福利一区二区在线| 无码精品不卡一区二区三区| 一本大道在线无码一区| 国产乱人伦精品一区二区在线观看| 久久99国产精一区二区三区| 91国偷自产一区二区三区| 中文字幕一区二区三匹| 国产一区二区免费在线| 亚洲日本一区二区一本一道| 人妻少妇精品一区二区三区| 日韩一区二区久久久久久| 精品国产一区二区三区av片| 精品一区二区高清在线观看| 在线|一区二区三区四区| 日本一区二区三区不卡视频| 冲田杏梨AV一区二区三区| 国产一区二区在线观看视频| 亚洲第一区精品观看| 农村人乱弄一区二区| 一区二区三区国产精品 | 精品人妻少妇一区二区三区不卡 | 一区二区三区无码被窝影院| 日本免费一区二区三区最新vr| 精品国产亚洲一区二区三区在线观看|