SSH免密登錄詳解

SSH免密登錄詳解

SSH(Security Shell)安全外殼協議,是較為可靠的,專為遠程登錄會話和其他網絡服務提供安全保證的協議。

​ 對於傳統的網絡服務程序(例如,FTP,Telnet等)來說,其本質上並不是安全的,主要原因在於,這些網絡應用程序在網絡上都是直接使用明文傳輸口令和數據的,對於別有用心的人來說,這些口令和數據是很容易被截獲的。另外,這些網絡服務程序的安全驗證方式也是存在弱點的,非常容易受到中間人(Man-In-The-Middle)這種方式的攻擊,簡而言之,就是中間人冒充真正的服務器接收你傳輸的數據,然後,再將數據轉發給真正的服務器,通過這種方式中間人就可以神不知鬼不覺地拿到你所有數據。

​ 通過使用SSH,則可以將所有傳輸的數據及口令進行加密,從而防止中間人攻擊,還可以防止DNS和IP欺騙,另外,使用SSH還有加快傳輸速度的好處,原因在於,SSH是可以對數據進行壓縮的。

SSH安裝詳解

SSH是安全外殼協議,而open-ssh則是SSH的開源實現,CentOS通常是默認安裝了open-ssh的。

整個SSH服務是包含SSH服務端(openssh-server)和SSH客戶端(openssh-clients)的,常用的ssh命令就是客戶端一部分。

SSH服務端與SSH客戶端之間的關係:節點A想要控制節點B,則節點A上需要安裝SSH客戶端,而節點B上需要安裝相應的SSH服務端,這樣,節點A才能向節點B發送控制命令和數據。

# 安裝openssh-server
[root@cos1 ~]# yum install -y openssh-server
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.ustc.edu.cn
 * extras: mirrors.ustc.edu.cn
 * updates: mirrors.ustc.edu.cn
Package openssh-server-7.4p1-21.el7.x86_64 already installed and latest version
# 啟動openssh-server
[root@cos1 ~]# systemctl start sshd.service
# 安裝openssh-clients
[root@cos1 ~]# yum install -y openssh-clients
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.ustc.edu.cn
 * extras: mirrors.ustc.edu.cn
 * updates: mirrors.ustc.edu.cn
Package openssh-clients-7.4p1-21.el7.x86_64 already installed and latest version

openssh服務的主配置文件路徑:/etc/ssh/sshd_config。

# SSH-Server常見的配置項
# 如果SSH連接提示端口不可用,可以在改文件中查看SSH端口,端口沒問題,就要考慮SSH服務是否正常啟動了
# SSH客戶端與服務端連接的默認端口號
Port 22

默認情況下,SSH服務提供了以下兩個非常有用的功能:

1、類似Telnet遠程連接服務器功能,即SSH服務(安全可靠的遠程登錄會話服務)

# 遠程連接服務
ssh user@hostname/ip

2、類似FTP的sftp-server服務,藉助SSH協議來傳輸數據,提供更安全的SFTP服務(vsftp, proftp).

# 文件拷貝服務
scp files user@hostname:/path/

SSH免密登錄配置

​ 對於分佈式環境組件(例如,Hadoop,HBase等)來說,組件的主/從節點通常需要遠程登錄到集群中其他節點並執行Shell命令,如果不使用SSH,則集群安全就無法保證,使用SSH服務的話,又需要用戶輸入目標服務器的免密,而主/從節點何時訪問其他節點是不可控的,而且,頻繁的需要用戶輸入密碼也是不可行的,這時候,免密登錄就非常重要的。

主機A通過SSH實現免密登錄主機B所需的配置過程大致可以分為以下兩步:

1、主機A在本地通過加密算法生成公鑰和私鑰

通過rsa算法生成公鑰和私鑰key對,默認情況下,身份驗證信息(也就是私鑰)保存在/user/.ssh/id_rsa文件下,而公鑰信息則保存在/user/.ssh/id_rsa.pub文件中。

[root@cos1 .ssh]# pwd
/root/.ssh
[root@cos1 .ssh]# ll
total 8
-rw-------. 1 root root 1679 Jun 22 00:04 id_rsa
-rw-r--r--. 1 root root  391 Jun 22 00:04 id_rsa.pub

2、將主機A的公鑰拷貝到主機B的授權文件(authorized_keys)中

# 通過ssh-copy-id命令將本地服務器公鑰上傳到指定服務器
[root@cos1 ~]# ssh-copy-id root@cos
... ... ... ... ... ... 
Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@cos'"
and check to make sure that only the key(s) you wanted were added.
# 現在,可以通過ssh root@cos訪問主機cos了
[root@cos1 ~]# ssh root@cos
Last login: Thu Jun 18 06:38:25 2020 from 192.168.58.1
[root@cos ~]# 

為了安全起見,通常將保存具體哪些主機可以免密訪問當前主機的授權文件authorized_keys文件設置為及root具有查看和修改的權限,用戶組及其他人無權訪問。

通過ssh-copy-id將主機A的公鑰拷貝到主機B之後,本質上,是在主機B的授權文件中添加了主機A的公鑰。

[root@cos .ssh]# ll
total 8
-rw-------. 1 root root 781 Jun 22 00:16 authorized_keys
-rw-r--r--. 1 root root 176 Jun 18 07:34 known_hosts

注意:

1、免密登錄,是用戶對用戶的,切換為其他用戶時,仍需要輸入密碼

2、免密登錄是單向的,也就是說,主機A將公鑰拷貝到主機B后,主機A可以免密登錄主機A,而主機B登錄主機A時仍然需要輸入密碼

圖解SSH免密登錄原理

通過上面一頓操作,主機A就可以免密登錄到主機A了,感覺有點神奇,那麼,免密登錄到底是怎麼實現的呢?也就是說,SSH協議又到底是什麼樣子呢?且看下圖分解~

上圖便是整個SSH免密登錄的配置及原理圖:

1、ServerA生成公鑰並上傳到ServerB上

2、Step 1: ServerA發送鏈接請求到ServerB

3、Step 2: ServerB在authorized_key中檢索ServerA的公鑰,隨機生成字符串,隨後利用公鑰對字符串進行加密,併發送給ServerA

4、Step 3: ServerA接收到密文後,利用私鑰進行解密,並將內容以明文的形式發送給ServerB

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

12.DRF-節流

Django rest framework源碼分析(3)—-節流

添加節流

自定義節流的方法

  • 限制60s內只能訪問3次

(1)API文件夾下面新建throttle.py,代碼如下:

# utils/throttle.py

from rest_framework.throttling import BaseThrottle
import time
VISIT_RECORD = {}   #保存訪問記錄

class VisitThrottle(BaseThrottle):
    '''60s內只能訪問3次'''
    def __init__(self):
        self.history = None   #初始化訪問記錄

    def allow_request(self,request,view):
        #獲取用戶ip (get_ident)
        remote_addr = self.get_ident(request)
        ctime = time.time()
        #如果當前IP不在訪問記錄裏面,就添加到記錄
        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr] = [ctime,]     #鍵值對的形式保存
            return True    #True表示可以訪問
        #獲取當前ip的歷史訪問記錄
        history = VISIT_RECORD.get(remote_addr)
        #初始化訪問記錄
        self.history = history

        #如果有歷史訪問記錄,並且最早一次的訪問記錄離當前時間超過60s,就刪除最早的那個訪問記錄,
        #只要為True,就一直循環刪除最早的一次訪問記錄
        while history and history[-1] < ctime - 60:
            history.pop()
        #如果訪問記錄不超過三次,就把當前的訪問記錄插到第一個位置(pop刪除最後一個)
        if len(history) < 3:
            history.insert(0,ctime)
            return True

    def wait(self):
        '''還需要等多久才能訪問'''
        ctime = time.time()
        return 60 - (ctime - self.history[-1])

(2)settings中全局配置節流

#全局
REST_FRAMEWORK = {
    #節流
    "DEFAULT_THROTTLE_CLASSES":['API.utils.throttle.VisitThrottle'],
}

(3)現在訪問auth看看結果:

  • 60s內訪問次數超過三次,會限制訪問
  • 提示剩餘多少時間可以訪問

接着訪問

節流源碼分析

(1)dispatch

def dispatch(self, request, *args, **kwargs):
    """
    `.dispatch()` is pretty much the same as Django's regular dispatch,
    but with extra hooks for startup, finalize, and exception handling.
    """
    self.args = args
    self.kwargs = kwargs
    #對原始request進行加工,豐富了一些功能
    #Request(
    #     request,
    #     parsers=self.get_parsers(),
    #     authenticators=self.get_authenticators(),
    #     negotiator=self.get_content_negotiator(),
    #     parser_context=parser_context
    # )
    #request(原始request,[BasicAuthentications對象,])
    #獲取原生request,request._request
    #獲取認證類的對象,request.authticators
    #1.封裝request
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?

    try:
        #2.認證
        self.initial(request, *args, **kwargs)

        # Get the appropriate handler method
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed

        response = handler(request, *args, **kwargs)

    except Exception as exc:
        response = self.handle_exception(exc)

    self.response = self.finalize_response(request, response, *args, **kwargs)
    return self.response

(2)initial

def initial(self, request, *args, **kwargs):
    """
    Runs anything that needs to occur prior to calling the method handler.
    """
    self.format_kwarg = self.get_format_suffix(**kwargs)

    # Perform content negotiation and store the accepted info on the request
    neg = self.perform_content_negotiation(request)
    request.accepted_renderer, request.accepted_media_type = neg

    # Determine the API version, if versioning is in use.
    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme

    # Ensure that the incoming request is permitted
    #4.實現認證
    self.perform_authentication(request)
    #5.權限判斷
    self.check_permissions(request)
    #6.控制訪問頻率
    self.check_throttles(request)

(3)check_throttles

裏面有個allow_request

def check_throttles(self, request):
    """
    Check if request should be throttled.
    Raises an appropriate exception if the request is throttled.
    """
    for throttle in self.get_throttles():
        if not throttle.allow_request(request, self):
            self.throttled(request, throttle.wait())

(4)get_throttles

def get_throttles(self):
    """
    Instantiates and returns the list of throttles that this view uses.
    """
    return [throttle() for throttle in self.throttle_classes]

(5)thtottle_classes

內置節流類

上面是寫的自定義節流,drf內置了很多節流的類,用起來比較方便。

(1)BaseThrottle

  • 自己要寫allow_request和wait方法
  • get_ident就是獲取ip
class BaseThrottle(object):
    """
    Rate throttling of requests.
    """

    def allow_request(self, request, view):
        """
        Return `True` if the request should be allowed, `False` otherwise.
        """
        raise NotImplementedError('.allow_request() must be overridden')

    def get_ident(self, request):
        """
        Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
        if present and number of proxies is > 0. If not use all of
        HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
        """
        xff = request.META.get('HTTP_X_FORWARDED_FOR')
        remote_addr = request.META.get('REMOTE_ADDR')
        num_proxies = api_settings.NUM_PROXIES

        if num_proxies is not None:
            if num_proxies == 0 or xff is None:
                return remote_addr
            addrs = xff.split(',')
            client_addr = addrs[-min(num_proxies, len(addrs))]
            return client_addr.strip()

        return ''.join(xff.split()) if xff else remote_addr

    def wait(self):
        """
        Optionally, return a recommended number of seconds to wait before
        the next request.
        """
        return None

(2)SimpleRateThrottle

class SimpleRateThrottle(BaseThrottle):
    """
    A simple cache implementation, that only requires `.get_cache_key()`
    to be overridden.

    The rate (requests / seconds) is set by a `rate` attribute on the View
    class.  The attribute is a string of the form 'number_of_requests/period'.

    Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day')

    Previous request information used for throttling is stored in the cache.
    """
    cache = default_cache
    timer = time.time
    cache_format = 'throttle_%(scope)s_%(ident)s'
    scope = None   #這個值自定義,寫什麼都可以
    THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES

    def __init__(self):
        if not getattr(self, 'rate', None):
            self.rate = self.get_rate()
        self.num_requests, self.duration = self.parse_rate(self.rate)

    def get_cache_key(self, request, view):
        """
        Should return a unique cache-key which can be used for throttling.
        Must be overridden.

        May return `None` if the request should not be throttled.
        """
        raise NotImplementedError('.get_cache_key() must be overridden')

    def get_rate(self):
        """
        Determine the string representation of the allowed request rate.
        """
        if not getattr(self, 'scope', None):
            msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
                   self.__class__.__name__)
            raise ImproperlyConfigured(msg)

        try:
            return self.THROTTLE_RATES[self.scope]
        except KeyError:
            msg = "No default throttle rate set for '%s' scope" % self.scope
            raise ImproperlyConfigured(msg)

    def parse_rate(self, rate):
        """
        Given the request rate string, return a two tuple of:
        <allowed number of requests>, <period of time in seconds>
        """
        if rate is None:
            return (None, None)
        num, period = rate.split('/')
        num_requests = int(num)
        duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
        return (num_requests, duration)

    def allow_request(self, request, view):
        """
        Implement the check to see if the request should be throttled.

        On success calls `throttle_success`.
        On failure calls `throttle_failure`.
        """
        if self.rate is None:
            return True

        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True

        self.history = self.cache.get(self.key, [])
        self.now = self.timer()

        # Drop any requests from the history which have now passed the
        # throttle duration
        while self.history and self.history[-1] <= self.now - self.duration:
            self.history.pop()
        if len(self.history) >= self.num_requests:
            return self.throttle_failure()
        return self.throttle_success()

    def throttle_success(self):
        """
        Inserts the current request's timestamp along with the key
        into the cache.
        """
        self.history.insert(0, self.now)
        self.cache.set(self.key, self.history, self.duration)
        return True

    def throttle_failure(self):
        """
        Called when a request to the API has failed due to throttling.
        """
        return False

    def wait(self):
        """
        Returns the recommended next request time in seconds.
        """
        if self.history:
            remaining_duration = self.duration - (self.now - self.history[-1])
        else:
            remaining_duration = self.duration

        available_requests = self.num_requests - len(self.history) + 1
        if available_requests <= 0:
            return None

        return remaining_duration / float(available_requests)

我們可以通過繼承SimpleRateThrottle類,來實現節流,會更加的簡單,因為SimpleRateThrottle裏面都幫我們寫好了

(1)throttle.py

from rest_framework.throttling import SimpleRateThrottle

class VisitThrottle(SimpleRateThrottle):
    '''匿名用戶60s只能訪問三次(根據ip)'''
    scope = 'NBA'   #這裏面的值,自己隨便定義,settings裏面根據這個值配置Rate

    def get_cache_key(self, request, view):
        #通過ip限制節流
        return self.get_ident(request)

class UserThrottle(SimpleRateThrottle):
    '''登錄用戶60s可以訪問10次'''
    scope = 'NBAUser'    #這裏面的值,自己隨便定義,settings裏面根據這個值配置Rate

    def get_cache_key(self, request, view):
        return request.user.username

(2)settings.py

#全局
REST_FRAMEWORK = {
    #節流
    "DEFAULT_THROTTLE_CLASSES":['API.utils.throttle.UserThrottle'],   #全局配置,登錄用戶節流限制(10/m)
    "DEFAULT_THROTTLE_RATES":{
        'NBA':'3/m',         #沒登錄用戶3/m,NBA就是scope定義的值
        'NBAUser':'10/m',    #登錄用戶10/m,NBAUser就是scope定義的值
    }
}

(3)views.py

局部配置方法

class AuthView(APIView):
    .
    .    
    .
    # 默認的節流是登錄用戶(10/m),AuthView不需要登錄,這裏用匿名用戶的節流(3/m)
    throttle_classes = [VisitThrottle,]   .    .
# views.py
from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView
from API import models
from rest_framework.request import Request
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
from API.utils.permission import SVIPPremission,MyPremission
from API.utils.throttle import  VisitThrottle

ORDER_DICT = {
    1:{
        'name':'apple',
        'price':15
    },
    2:{
        'name':'dog',
        'price':100
    }
}

def md5(user):
    import hashlib
    import time
    #當前時間,相當於生成一個隨機的字符串
    ctime = str(time.time())
    m = hashlib.md5(bytes(user,encoding='utf-8'))
    m.update(bytes(ctime,encoding='utf-8'))
    return m.hexdigest()


class AuthView(APIView):
    '''用於用戶登錄驗證'''

    authentication_classes = []      #裏面為空,代表不需要認證
    permission_classes = []          #不裏面為空,代表不需要權限
    # 默認的節流是登錄用戶(10/m),AuthView不需要登錄,這裏用匿名用戶的節流(3/m)
    throttle_classes = [VisitThrottle,]

    def post(self,request,*args,**kwargs):
        ret = {'code':1000,'msg':None}
        try:
            user = request._request.POST.get('username')
            pwd = request._request.POST.get('password')
            obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = '用戶名或密碼錯誤'
            #為用戶創建token
            token = md5(user)
            #存在就更新,不存在就創建
            models.UserToken.objects.update_or_create(user=obj,defaults={'token':token})
            ret['token'] = token
        except Exception as e:
            ret['code'] = 1002
            ret['msg'] = '請求異常'
        return JsonResponse(ret)


class OrderView(APIView):
    '''
    訂單相關業務(只有SVIP用戶才能看)
    '''

    def get(self,request,*args,**kwargs):
        self.dispatch
        #request.user
        #request.auth
        ret = {'code':1000,'msg':None,'data':None}
        try:
            ret['data'] = ORDER_DICT
        except Exception as e:
            pass
        return JsonResponse(ret)


class UserInfoView(APIView):
    '''
       訂單相關業務(普通用戶和VIP用戶可以看)
       '''
    permission_classes = [MyPremission,]    #不用全局的權限配置的話,這裏就要寫自己的局部權限
    def get(self,request,*args,**kwargs):

        print(request.user)
        return HttpResponse('用戶信息')

說明:

  • API.utils.throttle.UserThrottle 這個是全局配置(根據ip限制,10/m)
  • DEFAULT_THROTTLE_RATES —>>>設置訪問頻率的
  • throttle_classes = [VisitThrottle,] —>>>局部配置(不適用settings裏面默認的全局配置)

總結

基本使用

  • 創建類,繼承BaseThrottle, 實現:allow_request ,wait
  • 創建類,繼承SimpleRateThrottle, 實現: get_cache_key, scope=’NBA’ (配置文件中的key)

全局

   #節流
    "DEFAULT_THROTTLE_CLASSES":['API.utils.throttle.UserThrottle'],   #全局配置,登錄用戶節流限制(10/m)
    "DEFAULT_THROTTLE_RATES":{
        'NBA':'3/m',         #沒登錄用戶3/m,NBA就是scope定義的值
        'NBAUser':'10/m',    #登錄用戶10/m,NBAUser就是scope定義的值
    }
}

局部

throttle_classes = [VisitThrottle,]

所有代碼

認證、權限和節流

# MyProject/urls.py

from django.contrib import admin
from django.urls import path
from API.views import AuthView,OrderView,UserInfoView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/auth/',AuthView.as_view()),
    path('api/v1/order/',OrderView.as_view()),
    path('api/v1/info/',UserInfoView.as_view()),
]
#全局 settings.py
REST_FRAMEWORK = {
    #認證
    "DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',],
    #權限
    "DEFAULT_PERMISSION_CLASSES":['API.utils.permission.SVIPPermission'],
    #節流
    "DEFAULT_THROTTLE_CLASSES":['API.utils.throttle.UserThrottle'],   #全局配置,登錄用戶節流限制(10/m)
    "DEFAULT_THROTTLE_RATES":{
        'NBA':'3/m',         #沒登錄用戶3/m,NBA就是scope定義的值
        'NBAUser':'10/m',    #登錄用戶10/m,NBAUser就是scope定義的值
    }
}
# API/models.py


from django.db import models

class UserInfo(models.Model):
    USER_TYPE = (
        (1,'普通用戶'),
        (2,'VIP'),
        (3,'SVIP')
    )

    user_type = models.IntegerField(choices=USER_TYPE)
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)

class UserToken(models.Model):
    user = models.OneToOneField(UserInfo,on_delete=models.CASCADE)
    token = models.CharField(max_length=64)
# API/views.py

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView
from API import models
from rest_framework.request import Request
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
from API.utils.permission import SVIPPermission,MyPermission
from API.utils.throttle import  VisitThrottle

ORDER_DICT = {
    1:{
        'name':'apple',
        'price':15
    },
    2:{
        'name':'dog',
        'price':100
    }
}

def md5(user):
    import hashlib
    import time
    #當前時間,相當於生成一個隨機的字符串
    ctime = str(time.time())
    m = hashlib.md5(bytes(user,encoding='utf-8'))
    m.update(bytes(ctime,encoding='utf-8'))
    return m.hexdigest()


class AuthView(APIView):
    '''用於用戶登錄驗證'''

    authentication_classes = []      #裏面為空,代表不需要認證
    permission_classes = []          #不裏面為空,代表不需要權限
    # 默認的節流是登錄用戶(10/m),AuthView不需要登錄,這裏用匿名用戶的節流(3/m)
    throttle_classes = [VisitThrottle,]

    def post(self,request,*args,**kwargs):
        ret = {'code':1000,'msg':None}
        try:
            user = request._request.POST.get('username')
            pwd = request._request.POST.get('password')
            obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = '用戶名或密碼錯誤'
            #為用戶創建token
            token = md5(user)
            #存在就更新,不存在就創建
            models.UserToken.objects.update_or_create(user=obj,defaults={'token':token})
            ret['token'] = token
        except Exception as e:
            ret['code'] = 1002
            ret['msg'] = '請求異常'
        return JsonResponse(ret)


class OrderView(APIView):
    '''
    訂單相關業務(只有SVIP用戶才能看)
    '''

    def get(self,request,*args,**kwargs):
        self.dispatch
        #request.user
        #request.auth
        ret = {'code':1000,'msg':None,'data':None}
        try:
            ret['data'] = ORDER_DICT
        except Exception as e:
            pass
        return JsonResponse(ret)


class UserInfoView(APIView):
    '''
       訂單相關業務(普通用戶和VIP用戶可以看)
       '''
    permission_classes = [MyPermission,]    #不用全局的權限配置的話,這裏就要寫自己的局部權限
    def get(self,request,*args,**kwargs):

        print(request.user)
        return HttpResponse('用戶信息')
# API/utils/auth/py

from rest_framework import exceptions
from API import models
from rest_framework.authentication import BaseAuthentication


class Authentication(BaseAuthentication):
    '''用於用戶登錄驗證'''
    def authenticate(self,request):
        token = request._request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('用戶認證失敗')
        #在rest framework內部會將這兩個字段賦值給request,以供後續操作使用
        return (token_obj.user,token_obj)

    def authenticate_header(self, request):
        pass
# utils/permission.py

from rest_framework.permissions import BasePermission

class SVIPPermission(BasePermission):
    message = "必須是SVIP才能訪問"
    def has_permission(self,request,view):
        if request.user.user_type != 3:
            return False
        return True


class MyPermission(BasePermission):
    def has_permission(self,request,view):
        if request.user.user_type == 3:
            return False
        return True
# utils/throttle.py
#
# from rest_framework.throttling import BaseThrottle
# import time
# VISIT_RECORD = {}   #保存訪問記錄
#
# class VisitThrottle(BaseThrottle):
#     '''60s內只能訪問3次'''
#     def __init__(self):
#         self.history = None   #初始化訪問記錄
#
#     def allow_request(self,request,view):
#         #獲取用戶ip (get_ident)
#         remote_addr = self.get_ident(request)
#         ctime = time.time()
#         #如果當前IP不在訪問記錄裏面,就添加到記錄
#         if remote_addr not in VISIT_RECORD:
#             VISIT_RECORD[remote_addr] = [ctime,]     #鍵值對的形式保存
#             return True    #True表示可以訪問
#         #獲取當前ip的歷史訪問記錄
#         history = VISIT_RECORD.get(remote_addr)
#         #初始化訪問記錄
#         self.history = history
#
#         #如果有歷史訪問記錄,並且最早一次的訪問記錄離當前時間超過60s,就刪除最早的那個訪問記錄,
#         #只要為True,就一直循環刪除最早的一次訪問記錄
#         while history and history[-1] < ctime - 60:
#             history.pop()
#         #如果訪問記錄不超過三次,就把當前的訪問記錄插到第一個位置(pop刪除最後一個)
#         if len(history) < 3:
#             history.insert(0,ctime)
#             return True
#
#     def wait(self):
#         '''還需要等多久才能訪問'''
#         ctime = time.time()
#         return 60 - (ctime - self.history[-1])

from rest_framework.throttling import SimpleRateThrottle

class VisitThrottle(SimpleRateThrottle):
    '''匿名用戶60s只能訪問三次(根據ip)'''
    scope = 'NBA'   #這裏面的值,自己隨便定義,settings裏面根據這個值配置Rate

    def get_cache_key(self, request, view):
        #通過ip限制節流
        return self.get_ident(request)

class UserThrottle(SimpleRateThrottle):
    '''登錄用戶60s可以訪問10次'''
    scope = 'NBAUser'    #這裏面的值,自己隨便定義,settings裏面根據這個值配置Rate

    def get_cache_key(self, request, view):
        return request.user.username

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

南投信義望鄉部落一處山區,原住民保留地被大規模開墾

南投信義望鄉部落一處山區,原住民保留地被大規模開墾,面積高達兩公頃,就好像鬼剃頭。六月被檢舉遭到濫墾,縣府近日會同水保單位,以及公所進行勘驗,這名承租人原本是租了0.95公頃的原住民保留地,但濫墾面積卻將近一倍。

縣府會同水保單位勘驗,證實承租人租了0.95公頃的原住民保留地,卻濫墾將近一倍的面積,已正式公告違法屬實,違反水保法開罰12萬,承租人超挖土地部分,則要依期限改善造林。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※哪裡買的到省力省空間,方便攜帶的購物推車?

※廢氣洗滌塔,叫得動, 找得到的專業廠商‎

※市面十大品牌封口機!該如何選購?

※塑膠射出成型加工商品有哪些?

※選用哪種桶裝水,外宿露營超方便?

※各款電動堆高機價格?

※掌握產品行銷策略,帶你認識商品包裝設計基本要素

氣候變遷可能威脅物種生存,物種滅絕會影響生態系的健全

氣候變遷可能威脅物種生存,物種滅絕會影響生態系的健全,因此評估動物如何因應不斷變化的環境條件,以及這些變化是否能讓族群長期存續,是非常重要的工作。

為了回答這些問題,萊布尼茨動物園和野生動物研究所(Leibniz Institute for Zoo and Wildlife Research, Leibniz-IZW)學者瑞舒克(Viktoriia Radchuk)、寇提爾(Alexandre Courtiol)和克萊摩夏茲(Stephanie Kramer-Schadt)帶領64名研究人員組成國際團隊,回顧了10,000多份已發表的科學研究。

他們的結論是,儘管動物通常會對氣候變遷有所反應,例如改變繁殖時間,但這種反應通常不足以因應氣溫上升的速度,有時還會走錯方向。

歐洲斑姬鶲(European pied flycatcher)通常對環境變遷有一定適應能力。Aaron Maizlish攝(CC BY-NC 2.0)

他們將(Nature Communication)期刊。

共同作者、愛爾蘭科克大學資深講師里德(Thomas Reed)解釋,「我們將所觀察到的動物對氣候變遷的反應,和成功跟隨氣候變遷調整習性的反應做比較,得到這樣的結果。」

在野生動物中,最常見的氣候變遷反應是生物事件發生時間的改變,如冬眠、繁殖或遷徙。

體形、體重或其他形態特徵的變化也與氣候變遷有關,但是,正如該研究所證實,沒有顯示出系統性的變化模式。

研究人員從科學文獻中擷取相關資訊,尋找多年氣候變遷與兩種性狀的可能變化之間的關係。

接下來,他們評估觀察到的性狀變化是否與較高的存活率或後代數量的增加相關。

「我們的研究主要針對鳥類,因為其他群體的完整資料很少,」第一作者瑞舒克說,「我們證實,在溫帶地區,氣溫上升與生物事件發生時間的變化有關。」

另一位共同作者、加州大學柏克萊分校教授貝辛格(Steven Beissinger)指出:「這顯示只要物種適應夠快,足以因應氣候的變化,牠們也可以留在暖化的原棲地。」

但資深作者寇提爾提醒,「實際情況不太可能如此理想,因為即使是經歷過適應性變化的族群,也不保證可以一直以相同速度這麼做。」

更令人擔憂的是,所分析的資料涵蓋如大山雀(Parus major)、歐洲斑姬鶲(Ficedula hypoleuca),或常見的西方喜鵲(Pica pica),這些已知適應良好、數量充足的物種。

「稀有或瀕危物種的適應力仍有待分析。」Leibniz-IZW生態動力學部負責人克萊摩夏茲總結道,「我們擔心這些物種的存續前景會更加悲觀。」

科學家們希望他們分析彙整的資料集能夠帶來更多全球氣候變遷下動物族群恢復力研究,並有助建立更好的預測方法,協助未來的保護管理行動。

Wildlife Changing Too Slowly to Survive Climate Change BERLIN, Germany, July 23, 2019 (ENS)

Climate change can threaten species and extinctions can impact ecosystem health, so it is of vital importance to assess how animals respond to changing environmental conditions, and whether these shifts enable the persistence of populations in the long run.

To answer these questions an international team of 64 researchers led by Viktoriia Radchuk, Alexandre Courtiol and Stephanie Kramer-Schadt from the Leibniz Institute for Zoo and Wildlife Research (Leibniz-IZW) evaluated more than 10,000 published scientific studies.

They concluded that although animals do commonly respond to climate change, for example by shifting the timing of breeding, such responses are in general insufficient to cope with the rapid pace of rising temperatures and sometimes go in wrong directions.

Their findings are published in the scientific journal “Nature Communications.”

Co-author Thomas Reed, a senior lecturer at University College Cork, Ireland, explains, “These results were obtained by comparing the observed response to climate change with the one expected if a population would be able to adjust their traits so to track the climate change perfectly.”

In wildlife, the most commonly observed response to climate change is an alteration in the timing of biological events such as hibernation, reproduction or migration.

Changes in body size, body mass or other morphological traits have also been associated with climate change, but, as confirmed by this study, show no systematic pattern.

The researchers extracted relevant information from the scientific literature to relate changes in climate over the years to possible changes in both types of traits.

Next, they evaluated whether observed trait changes were associated with higher survival or an increased number of offspring.

“Our research focused on birds because complete data on other groups were scarce,” says lead author Radchuk. “We demonstrate that in temperate regions, the rising temperatures are associated with the shift of the timing of biological events to earlier dates.”

Co-author Steven Beissinger, a professor at the University of California, Berkeley, said, “This suggests that species could stay in their warming habitat, as long as they change fast enough to cope with climate change.”

Senior author Alexandre Courtiol said, “This is unlikely to be the case because even populations undergoing adaptive change do so at a pace that does not guarantee their persistence.”

Even more worrisome is the fact that the data analyzed included predominantly common and abundant species such as the great tit, Parus major, the European pied flycatcher, Ficedula hypoleuca, or the common magpie, Pica pica, which are known to cope with climate change relatively well.

“Adaptive responses among rare or endangered species remain to be analyzed. We fear that the forecasts of population persistence for such species of conservation concern will be even more pessimistic,” concludes Stephanie Kramer-Schadt, who heads the Department of Ecological Dynamics at Leibniz- IZW.

The scientists hope that their analysis and the assembled datasets will stimulate research on the resilience of animal populations in the face of global change and contribute to a better predictive framework to assist future conservation management actions.

※ 全文及圖片詳見:

※ 本文與 行政院農業委員會林務局 合作刊登

作者

如果有一件事是重要的,如果能為孩子實現一個願望,那就是人類與大自然和諧共存。

於特有生物研究保育中心服務,小鳥和棲地是主要的研究對象。是龜毛的讀者,認為龜毛是探索世界的美德。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※無塵擦拭紙各大品牌廠商販售比價網!

※如何知道自已的電腦cpu支不支持AVX指令集?

※如何正確使用飲水機?

※攻戰消費者第一視覺,包裝設計很重要!

※滑鼠墊適用各種文宣活動廣告曝光,專業客製服務

※封口機購物網-不怕你比價,就怕你買貴!

※高溫殺菌機最多可達多少溫度?

日本琉球新報報導,民眾2日目擊有鯊魚現蹤那霸市國場川

日本琉球新報報導,民眾2日目擊有鯊魚現蹤那霸市國場川,經專家確認,河川內的是公牛幼鯊。由於河川附近有學校及幼稚園,不少家長擔如果孩童不慎落水可能遭遇危險。

魚類專家富田武照說,公牛鯊(Bull Shark),雖被歸類是「對人類最具威脅的一種鯊魚」,但成鯊從未被發現出現在沖繩河川中;幼鯊長度約一公尺,就算進入河川中,也幾乎沒有發生過幼鯊攻擊人類的案例。不過,研究鯊魚的專家們目前仍不清楚鯊魚為何進入河川。琉球大學理學系教授立原一憲說,公牛鯊會出現在河川,在全球都屬罕見景況,希望釣客不要把幼鯊釣上岸,合力保育這群稀有物種。

國際自然保護聯盟(IUCN)明訂公牛鯊屬近危物種,沖繩縣「紅色名錄」(可能滅絕物種名單)也記載公牛鯊需被保護。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※無塵擦拭紙各大品牌廠商販售比價網!

※如何正確使用飲水機?

※如何知道自已的電腦cpu支不支持AVX指令集?

※掌握產品行銷策略,帶你認識商品包裝設計基本要素

※商業用玻璃煎台不必開大火也能迅速導熱

※選用哪種桶裝水,外宿露營超方便?

※空壓機這裡買最划算!

緬甸北部克欽邦(Kachin State)帕坎鎮(Hpakant)

緬甸北部克欽邦(Kachin State)帕坎鎮(Hpakant)的一座玉礦場27日深夜爆發土石流,造成14人死亡,另有4人失蹤且生還機率渺茫。帕坎鎮所在地區的警察首長丹溫翁(Than Win Aung)告訴路透社,他們已在事故地點找到14具遺體,另有4人失蹤,包括2名看守礦場的警員。

當地經常發生致命礦災。4月一處礦場上方的池塘潰決,造成在下方山坡開採的55名礦工喪生,當局也以安全為由暫時禁止17座玉礦場開採。

13 people, including one policeman, were killed by a massive landslide which hit a jade mine in Hpakant township, and 5 are still missing, Myanmar’s northernmost Kachin state, on Sunday.
The incident occurred around 2:30 am local time.

— CCTV Asia Pacific (@CCTVAsiaPacific)

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※客製專屬滑鼠墊、可愛造型L夾、L型資料夾、透明證件套、手提袋,專業印刷設計廠商!  

※示波器鮮為人知的使用技巧?

※掌握產品行銷策略,帶你認識商品包裝設計基本要素

※買不起高檔茶葉,精緻包裝茶葉罐,也能撐場面!

※各種升降平台款式?

※高效率洗滌塔活性碳設備有哪些?

※空壓機這裡買最划算!

日本總務省消防廳公佈最新統計,全日本在22日至28日的一週內

日本總務省消防廳公佈最新統計,全日本在22日至28日的一週內,共有5664人疑因中暑送醫,其中在11個府縣共有11人不幸死亡,可能跟梅雨季剛結束氣溫突然飆升有關。

從年齡別來看,65歲以上高齡者有2978人中暑送醫,佔逾半數的52.6%。從地區別來看,中暑送醫最多的是愛知縣392人,其次是大阪府388人及東京都299人。最容易發生中暑情況的地方竟是家裡,有1993人;在包括人行道的路上中暑的也有957人;而在學校中暑的則有299人。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※哪裡買的到省力省空間,方便攜帶的購物推車?

※廢氣洗滌塔,叫得動, 找得到的專業廠商‎

※市面十大品牌封口機!該如何選購?

※塑膠射出成型加工商品有哪些?

※選用哪種桶裝水,外宿露營超方便?

※各款電動堆高機價格?

※掌握產品行銷策略,帶你認識商品包裝設計基本要素

川普政府打算撤銷歐巴馬時代設立的聯邦車輛減排政策-2020至2060車型年

環境資訊中心外電;姜唯翻譯;林大利審校;稿源:ENS

川普政府打算撤銷歐巴馬時代設立的聯邦車輛減排政策-2020至2060車型年,車輛排放不可再增加。但四大汽車製造商和加州政府已就達成自主減排共識,包括汽油、柴油汽車和輕型卡車將繼續遵循現行歐巴馬政府時代設立的淨化速度標​​準直至2026,鼓勵創新以加速過渡電動汽車,並提供產業投資和創造就業機會所需的確定性。

加州的交通狀況。攝(CC0 1.0)

同意該規範的汽車製造商包括福特、本田、北美寶馬和美國福斯。自願加入規範的汽車公司在美國只能銷售符合這些標準的汽車。

「沒有什麼問題比氣候變遷更迫切,氣候變遷是危及我們生命和生計的全球性威脅。加州等多個州政府和合作汽車製造商正在引領能讓空氣更乾淨、安全的智慧政策」加州州長紐森(Gavin Newsom)說,「現在我呼籲其他汽車業加入,讓川普政府採納這種務實的折衷辦法,而不是一味開政策倒車。這對我們的經濟、人民和地球都是正確的作法。 」

「這項合作協議是實現加州和汽車工業目標的可行、可接受途徑,」加州空氣資源委員會主席尼科爾斯(Mary Nichols)說,「如果白宮不同意,我們將繼續遵循現行標準,但與個別汽車製造商合作實施這些原則。同時,如果目前的聯邦汽車標準定案,我們仍將繼續執行我們的規範,並對聯邦法規提出法律上的挑戰。」

加州州長紐森辦公室聲明指出,川普此舉威脅數百萬美國人的空氣品質和健康狀況,將增加消費者的成本,並可能進一步阻礙美國因應氣候變遷的努力。

多個州長、市長、汽車公司、勞工、消費者團體、公共衛生組織和環保組織亦群起反彈。

本月稍早,24名州長跨黨派組成聯盟,代表了超過一半的美國人口,共同呼籲建立更積極的國家乾淨車輛標準。

州長們發表「國家乾淨車輛承諾」聲明,呼籲依照常識,保護國家在談判桌上地位,並建立強而有力的國家標準。

「我們必須合作確保加州和全國能有一個強而有力、以科學為基礎的國家標準,這個標準要逐年提高,為汽車製造商和消費者提供確定性,減少溫室氣體排放,並保護公眾健康。 」

該聲明不僅有13個遵循加州車輛標準的州簽署,其他10個由共和黨和民主黨州長領導的州也加入。這個跨黨派聯盟共占美國經濟57%,占美國年度汽車銷售量的一半以上。

加州空氣資源委員會與加拿大今年6月剛簽署合作備忘錄,承諾兩國政府合作制定法規,以減少自小客車和輕型貨車的排放,目前加拿大、加州和美國13個州都採納加州排放標準。

川普撤銷排放規範可能排放數十億噸溫室氣體、數百萬噸顆粒物質和臭氧污染物至大氣中。根據美國環境保護署估計,到2025年,全國撤銷排放規範帶來的健康相關成本可高達120億美元。

上個月,全球17家汽車製造商呼籲白宮和加州共同製定單一的國家標準,避免汽車市場的不確定性、汽車業工作機會受到威脅。

Automakers Reject Trump Rollback of Clean Car Standards SACRAMENTO, California, July 26, 2019 (ENS)

As the Trump administration prepares to roll back emission standards for light-duty cars and trucks, a consortium of four automakers and the state of California have agreed on a voluntary framework to reduce emissions as an alternative path forward for clean vehicle standards nationwide.

Automakers who agreed to the framework are Ford, Honda, BMW of North America and Volkswagen Group of America.

The framework supports continued annual reductions of vehicle greenhouse gas emissions through the 2026 model year, encourages innovation to accelerate the transition to electric vehicles, and provides industry the certainty needed to make investments and create jobs.

This commitment means that the auto companies party to the voluntary agreement will only sell cars in the United States that meet these standards.

“Few issues are more pressing than climate change, a global threat that endangers our lives and livelihoods. California, a coalition of states, and these automakers are leading the way on smart policies that make the air cleaner and safer for us all,” said California Governor Gavin Newsom.

“I now call on the rest of the auto industry to join us, and for the Trump administration to adopt this pragmatic compromise instead of pursuing its regressive rule change,” Newsome said. “It’s the right thing for our economy, our people and our planet.”

Under the framework, gasoline and diesel cars and light trucks will get cleaner through 2026 at about the same rate as they would under the current program, adopted under the Obama administration.

“This agreement represents a feasible and acceptable path to accomplishing the goals of California and the automobile industry,” said California Air Resources Board Chair Mary Nichols.

“If the White House does not agree, we will move forward with our current standards but work with individual carmakers to implement these principles,” said Nichols. “At the same time, if the current federal vehicle standards proposal is finalized, we will continue to enforce our regulations and pursue legal challenges to the federal rule.”

The agreement comes as the Trump administration is preparing to roll back federal vehicle emission standards, freezing them at the 2020 level through the 2026 model year. This move threatens air quality and health for millions of Americans, would increase costs to consumers, and promises to further set back U.S. efforts to combat climate change, Governor Newsom’s office said in a statement.

The rollback has faced growing opposition from a broad array of governors and mayors, auto companies, labor, consumer groups, public health organizations, and environmental groups.

Earlier this month, a bipartisan coalition of 24 governors representing more than half the U.S. population came together in calling for a stronger, national clean car standard.

In their statement, entitled “The Nation’s Clean Car Promise,” the governors called for a commonsense approach that protects the role of states at the negotiating table and establishes a strong, national standard.

“We must unite to ensure a strong, science-based national standard, in California and across the country, that increases year-over-year, provides certainty for automakers and consumers, reduces greenhouse gases, and protects public health,” the 24 governors said.

The statement is signed not just by the 13 states that follow California’s clean car standards, but by 10 additional states led by both Republican and Democratic governors. Together, this bipartisan coalition represents 57 percent of the U.S. economy and more than half of U.S. annual auto sales.

In June, the California Air Resources Board signed a Memorandum of Understanding with Canada committing both governments to work together on developing their respective regulations to cut emissions from light-duty vehicles, such as those currently in effect in Canada, California and the 13 U.S. states that have adopted California’s standards.

Trump’s proposed rollback threatens to pump billions of tons of climate-altering greenhouse gases, as well as millions of tons of particulate matter and ozone-causing pollutants, into the atmosphere. By the US Environmental Protection Agency’s own estimates, health-related costs from the rollback could be as much as $12 billion nationally by 2025.

In a letter last month, 17 worldwide automakers appealed to the White House and California to work together on a single national standard, warning of uncertainty for the auto market and noting that auto industry jobs are at stake.

※ 全文及圖片詳見:

作者

如果有一件事是重要的,如果能為孩子實現一個願望,那就是人類與大自然和諧共存。

於特有生物研究保育中心服務,小鳥和棲地是主要的研究對象。是龜毛的讀者,認為龜毛是探索世界的美德。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

※哪裡買的到省力省空間,方便攜帶的購物推車?

※廢氣洗滌塔,叫得動, 找得到的專業廠商‎

※市面十大品牌封口機!該如何選購?

※塑膠射出成型加工商品有哪些?

※選用哪種桶裝水,外宿露營超方便?

※各款電動堆高機價格?

※掌握產品行銷策略,帶你認識商品包裝設計基本要素

新北市長侯友宜表示,五股垃圾山整頓計畫難度很高

新北市長侯友宜表示,五股垃圾山整頓計畫難度很高,歷任縣市長沒有人想碰觸,如果要等到都市計畫通過,「我看十年也過不了」,廢土若全數移除,估計須花費100億元。五股垃圾山不只有垃圾問題,還有很多違章工廠、廢棄土甚至賭場等,藏污納垢,試辦計畫有時間、步驟、方法,新北市城鄉局已把期程排出,希望在2021年12月31日前,完成五股垃圾山簡易綠化。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※無塵擦拭紙各大品牌廠商販售比價網!

※如何知道自已的電腦cpu支不支持AVX指令集?

※如何正確使用飲水機?

※攻戰消費者第一視覺,包裝設計很重要!

※滑鼠墊適用各種文宣活動廣告曝光,專業客製服務

※封口機購物網-不怕你比價,就怕你買貴!

※高溫殺菌機最多可達多少溫度?

台30線南安瀑布附近又有小熊在大馬路徘徊

台30線南安瀑布附近又有小熊在大馬路徘徊,30日早上10點多被爬山民眾用手機拍到。林務局花蓮林管處表示,目前密切「觀察」中,暫時不會有人為介入,希望母熊早日回來找小熊。



民眾提供

拍到小熊的崔姓民眾表示,在接近瓦拉米步道口之前的轉彎處,看到小黑熊過馬路,他怕撞到熊趕快踩煞車,拿起手機要拍,但牠很快就走到下邊坡處,從拍到的畫面發現小黑熊身上有些皮膚病,造成軀幹、四肢毛皮有少部份脫落。他說,到步道後碰到當地原住民,對方告知,29日就已經有民眾看到熊,其實山區一直都有熊,有大熊有小熊,希望民眾不要幹擾牠。

花蓮林管處獸醫楊青樺說,民眾僅目擊有小熊,但不代表母熊沒有在附近,因為小熊行動速度較慢,成年母熊比較靈敏,因此民眾這幾天到山區活動,一旦看到小熊也不要太靠近,以免突然遭受母熊攻擊;人為過度幹擾之下,也可能使得母熊放棄帶走小熊,造成小熊失去媽媽照顧,希望在盡可能減輕幹擾下,讓母熊自行回來帶走小熊。

※ 本文與 行政院農業委員會林務局 合作刊登

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※無塵擦拭紙各大品牌廠商販售比價網!

※如何正確使用飲水機?

※如何知道自已的電腦cpu支不支持AVX指令集?

※掌握產品行銷策略,帶你認識商品包裝設計基本要素

※商業用玻璃煎台不必開大火也能迅速導熱

※選用哪種桶裝水,外宿露營超方便?

※空壓機這裡買最划算!