Diffie-Hellman密鑰協商算法_租車

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

日本、大陸,發現這些先進的國家已經早就讓電動車優先上路,而且先進國家空氣品質相當好,電動車節能減碳可以減少空污

概述

DH算法是非對稱加密算法的鼻祖,為非對稱加密算法奠定了基礎,主要用途是進行密鑰交換確保共享的密鑰能夠安全穿越不安全的網絡。該算法其背後有對應數學理論做支撐,簡單來講就是構造一個複雜的計算難題,使得對該問題的求解在現實的時間內無法快速有效的求解(computationally infeasible )。

這個機制的巧妙在於需要安全通信的雙方可以用這個方法確定對稱密鑰。然後可以用這個對稱密鑰進行加密和解密。但是注意,這個密鑰交換協議/算法只能用於密鑰的交換,而不能進行消息的加密和解密。之所以如此,主要還是由於對稱加密和非對稱加密算法的特性決定的。

1. 對稱加密算法和非對稱加密算法

對稱加密算法

雙方使用的同一個密鑰,既可以加密又可以解密,這種加密方法稱為對稱加密,也稱為單密鑰加密。

優點:速度快,對稱性加密通常在消息發送方需要加密大量數據時使用,算法公開、計算量小、加密速度快、加密效率高。

缺點:在數據傳送前,發送方和接收方必須商定好秘鑰,然後 使雙方都能保存好秘鑰。其次如果一方的秘鑰被泄露,那麼加密信息也就不安全了。另外,每對用戶每次使用對稱加密算法時,都需要使用其他人不知道的唯一秘鑰,這會使得收、發雙方所擁有的鑰匙數量巨大,密鑰管理成為雙方的負擔。

在對稱加密算法中常用的算法有:DES、AES等。

AES:密鑰的長度可以為128、192和256位,也就是16個字節、24個字節和32個字節。

DES:密鑰的長度64位,8個字節。

非對稱加密算法

一對密鑰由公鑰和私鑰組成(可以使用很多對密鑰)。私鑰解密公鑰加密數據,公鑰解密私鑰加密數據(私鑰公鑰可以互相加密解密)。私鑰只能由一方保管,不能外泄。公鑰可以交給任何請求方。

優點:安全。

缺點:速度較慢。

在非對稱加密算法中常用的算法有: DH,RSA等。

兩者區別

  • 算法複雜度:對稱密鑰<非對稱密鑰
  • 加解密速度:對稱密鑰>非對稱密鑰
  • 安全性:對稱密鑰<非對稱密鑰

對稱加密算法相比非對稱加密算法來說,加解密的效率要高得多。但是缺陷在於對於秘鑰的管理上,以及在非安全信道中通訊時,密鑰交換的安全性不能保障。所以在實際的網絡環境中,會將兩者混合使用。因此 ,在https中(TLS\SSL)握手階段使用非對稱加密進行對稱密鑰的協商,而後在後續正常的數據傳輸時,都會使用對稱加密算法進行加密傳輸。

數學基礎

本原根:如果使得 \(a^{m}\equiv 1\ \left( mod\ n \right)\) 成立的最小正冪 \(m\) 滿足 $m=\varphi \left( n \right) $ ,則稱 \(a\)\(n\) 的本原根。 其中 \(\varphi \left( n \right)\) 為歐拉函數。

性質:若 \(a\) 為模 \(n\) 的本原根,則 \(a\)\(a\) 的平方,\(a\) 的3次方,……,\(a\)\(\varphi \left( n \right)\) 次m方 模 \(n\) 的餘數互不相同,而且構成一個模n的簡化剩餘系。

栗子(原根):設 \(n=7\),則 \(\varphi \left( 7 \right) =7\times \left( 1-\frac{1}{7} \right) =6\)

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

有別於一般網頁架設公司,除了模組化的架站軟體,我們的營業主軸還包含:資料庫程式開發、網站建置、網頁設計、電子商務專案開發、系統整合、APP設計建置、專業網路行銷。

  • \(n=2\) 時,我們需要找到一個 \(m\), 使得 \(2^m\%7=1\),且剛好 \(m==\varphi \left( 7 \right)\),首先我們能找到當 \(m=3\) 時,\(2^3\%7=1\),但是卻不等於 \(\varphi \left( 7 \right)\),因此不滿足。
  • \(n=3\)時,類比上面一點,可以發現 \(m=6\) 時,兩點都能滿足。因此 \(3\)\(7\) 的一個原根。

question:找了很多資料對原本根和原根的區別,還是很含糊!有大神的話,希望能教教我,感謝啦!

算法流程及原理

假設Alice需要與Bob協商一個秘鑰(秘鑰本質上就是一個比特序列,從計算的角度看就是一個大數)。

  1. 首先Alice與Bob共享一個素數 \(p\) 以及該素數 \(p\) 的本原根 \(g\) (generator),且 \(2\le g\le p-1\)。這兩個數可以不經過加密的由一方發送到另一方,至於誰發送給誰並不重要,只要保證雙方都能知道 \(p\)\(g\) 即可。
  1. 而後Alice產生一個私有的隨機數 \(A\),滿足 \(1\le A\le p-1\),然後計算 \(g^Amod\ p=Y_a\),將結果 \(Y_a\) 通過公網發送給Bob; 與此同時,Bob也產生一個私有的隨機數 \(B\),滿足 \(1\le B\le p-1\),計算 \(g^Bmod\ p=Y_b\),再將結果 \(Y_b\) 通過公網發送給Alice。
  1. 此時Alice知道的信息有\(p\),\(g\),\(A\),\(Y_a\),\(Y_b\),其中数字 \(A\) 是Alice私有的,只有她自己知道,其他的信息都是別人可能知道的;同樣Bob知道的信息有\(p\),\(g\),\(A\),\(Y_a\),\(Y_b\),其中数字 \(B\) 是Bob私有的,只有自己知道。

    到目前為止,Alice和Bob之間的密鑰協商結束。

    Alice通過計算 \(K_a=\left( Y_b \right) ^A\ mod\ p\) 得到密鑰 \(K_a\),同樣的,Bob通過計算 \(K_b=\left( Y_a \right) ^B\ mod\ p\) 得到密鑰 \(K_b\),可以證明,必然滿足 \(K_a=K_b\)。由此,Alice和Bob得到了相同的密鑰,達成了密鑰協商的目的。

    證明:\(K_a=K_b\)

    對於Alice有:

    \(K_a=\left( Y_b \right) ^Amod\ p=\left( g^Bmod\ p \right) ^A\ mod\ p=g^{B\times A}\ mod\ p\)

    對於Bob有:

    \(K_b=\left( Y_a \right) ^Bmod\ p=\left( g^Amod\ p \right) ^B\ mod\ p=g^{A\times B}\ mod\ p\)

    上面的運算過程,可根據取模運算的性質可得【a ^ b % p = ((a % p)^b) % p】,由上可得,Alice和Bob生成的密鑰其實是進行相同的運算過程,因此必然有 \(K_a=K_b\)

  2. 如果存在一個竊聽者Eve,他能否破解密鑰呢?很顯然Eve能夠竊聽到 \(p\),\(g\),\(Y_a\),\(Y_b\),所以問題轉變了,Eve能否根據這些信息計算出 \(K_a\)\(K_b\) ?要計算 \(K_a\)\(K_b\) 需要知道A和B。

    以計算A為例,Eve能根據 \(p\),\(g\),\(Y_a\) 通過 \(g^Amod\ p=Y_a\) 計算出 \(A\) 嗎? 目前所知的最佳算法Pollard’s rho algorithm for logarithms 時間複雜度是 \(O\left( \sqrt{p} \right)\), 但是實際應用中的 \(p\) 為二進制,假設這個 \(p\) 的長度為 \(n\), 這個複雜度實際上是 $O\left( 2^{\frac{n}{2}} \right) $,這個一個指數級的複雜度,是非常高的。因此求解該問題在計算上的困難程度保證了DH算法的安全性。

安全性問題

那DH密鑰協商算法是否就一定安全呢?我們所熟知的,存在一種偽裝者攻擊(中間人攻擊)能夠對這種密鑰協商算法造成威脅。

假設密鑰協商過程中,在Alice和Bob有一個稱為Alan的主動攻擊者,他能夠截獲Alice和Bob的消息並偽造假消息,考慮以下情況。

  1. Alice和Bob已經共享一個素數 \(p\) 以及其該素數 \(p\) 的本原根 \(g\),當然Alan也監聽到報文得知了這個兩個消息。
  2. 此時Alice計算 \(g^Amod\ p=Y_a\) ,然而將 \(Y_a\) 發送給Bob的過程中被Alan攔截了,Alan自己選定了一個隨機數 \(C\), 計算 \(Y_c=g^C\ mod\ p\), 然後將 \(Y_c\) 發送給Bob。
  1. 同時Bob計算 \(g^Bmod\ p=Y_b\),同樣在將 \(Y_b\) 發送給Alice的過程中被Alan攔截下來,Alan自己選定了一個隨機數D ,計算 \(g^Dmod\ p=Y_d\) 發送給了Alice
  1. 由於Alice和Bob通訊的消息被替換,Alice計算出來的密鑰實際上為Alice和Alan之間協商的密鑰:\(K_{ad}=g^{D\times A}\ mod\ p\);Bob計算出來的密鑰實際上是Blob和Alan之間協商的密鑰:\(K_{bc}=g^{C\times B}\ mod\ p\) 。如果之後Alice和Bob用他們各自計算出來的密鑰加密任何信息,Alan截獲之後都能夠解密得到明文,而Alan也能夠偽裝成Alice或者Bob給雙方發消息,而不至於被發現。

代碼為java實現。

參考

https://www.cnblogs.com/qcblog/p/9016704.html

https://www.cnblogs.com/wushaopei/p/11979200.html

https://blog.csdn.net/l18339702017/article/details/81625257

https://www.jiamisoft.com/blog/24603-dcfdcjm.html

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

※超省錢租車方案

商務出差、學生出遊、旅遊渡假、臨時用車!GO 神州租賃有限公司!合法經營、合法連鎖、合法租賃小客車!

結合 AOP 輕鬆處理事件發布處理日誌_包裝設計

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

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

結合 AOP 輕鬆處理事件發布處理日誌

Intro

前段時間,實現了 EventBus 以及 EventQueue 基於 Event 的事件處理,但是沒有做日誌(EventLog)相關的部分,原本想增加兩個接口, 處理事件發布日誌和事件處理日誌,最近用了 AOP 的思想處理了 EntityFramework 的數據變更自動審計,於是想着事件日誌也用 AOP 的思想來實現,而且可能用 AOP 來處理可能會更好一些,最近自己造了一個 AOP 的輪子 —— FluentAspects,下面的示例就以它來演示了,你也可以換成自己喜歡的 AOP 組件,思想是類似的

事件日誌示例

事件發布日誌

事件發布日誌只需要攔截事件發布的方法調用即可,在發布事件時進行攔截,在攔截器中根據需要進行日誌記錄即可

事件發布者接口定義:

public interface IEventPublisher
{
    /// <summary>
    /// publish an event
    /// </summary>
    /// <typeparam name="TEvent">event type</typeparam>
    /// <param name="event">event data</param>
    /// <returns>whether the operation succeed</returns>
    bool Publish<TEvent>(TEvent @event) where TEvent : class, IEventBase;

    /// <summary>
    /// publish an event async
    /// </summary>
    /// <typeparam name="TEvent">event type</typeparam>
    /// <param name="event">event data</param>
    /// <returns>whether the operation succeed</returns>
    Task<bool> PublishAsync<TEvent>(TEvent @event) where TEvent : class, IEventBase;
}

事件發布日誌攔截器:

public class EventPublishLogInterceptor : AbstractInterceptor
{
    public override async Task Invoke(IInvocation invocation, Func<Task> next)
    {
        Console.WriteLine("-------------------------------");
        Console.WriteLine($"Event publish begin, eventData:{invocation.Arguments.ToJson()}");
        var watch = Stopwatch.StartNew();
        try
        {
            await next();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Event publish exception({ex})");
        }
        finally
        {
            watch.Stop();
            Console.WriteLine($"Event publish complete, elasped:{watch.ElapsedMilliseconds} ms");
        }
        Console.WriteLine("-------------------------------");
    }
}

事件處理日誌

事件處理器接口定義:

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

public interface IEventHandler
{
    Task Handle(object eventData);
}

事件處理日誌攔截器定義:

public class EventHandleLogInterceptor : IInterceptor
{
    public async Task Invoke(IInvocation invocation, Func<Task> next)
    {
        Console.WriteLine("-------------------------------");
        Console.WriteLine($"Event handle begin, eventData:{invocation.Arguments.ToJson()}");
        var watch = Stopwatch.StartNew();
        try
        {
            await next();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Event handle exception({ex})");
        }
        finally
        {
            watch.Stop();
            Console.WriteLine($"Event handle complete, elasped:{watch.ElapsedMilliseconds} ms");
        }
        Console.WriteLine("-------------------------------");
    }
}

AOP 配置

Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(builder =>
    {
        builder.UseStartup<Startup>();
    })
    .UseFluentAspectsServiceProviderFactory(options =>
    {
        // 攔截器配置
        
        // 攔截 `IEventPublisher` 日誌,註冊事件發布日誌攔截器
        options
            .InterceptType<IEventPublisher>()
            .With<EventPublishLogInterceptor>();

        // 攔截 `IEventHandler`,註冊事件處理日誌攔截器
        options.InterceptType<IEventHandler>()
            .With<EventHandleLogInterceptor>();
    }, builder =>
    {
        // 默認使用默認實現來生成代理,現在提供了 Castle 和 AspectCore 的擴展,也可以自己擴展實現自定義代理生成方式
        // 取消註釋使用 Castle 來生成代理
        //builder.UseCastleProxy();
    }, t => t.Namespace?.StartsWith("WeihanLi") == false // 要忽略的類型斷言
    )
    .Build()
    .Run();

More

事件發布示例,定義了一個發布事件的中間件:

// pageView middleware
app.Use((context, next) =>
{
    var eventPublisher = context.RequestServices
        .GetRequiredService<IEventPublisher>();
    eventPublisher.Publish(new PageViewEvent()
    {
        Path = context.Request.Path.Value,
    });

    return next();
});

事件處理示例是用一個消息隊列的模式來處理的,示例和前面的事件的文章類似,EventConsumer 是一個後台任務,完整代碼示例如下:

public class EventConsumer : BackgroundService
{
    private readonly IEventQueue _eventQueue;
    private readonly IEventHandlerFactory _eventHandlerFactory;

    public EventConsumer(IEventQueue eventQueue, IEventHandlerFactory eventHandlerFactory)
    {
        _eventQueue = eventQueue;
        _eventHandlerFactory = eventHandlerFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var queues = await _eventQueue.GetQueuesAsync();
            if (queues.Count > 0)
            {
                await queues.Select(async q =>
                        {
                            var @event = await _eventQueue.DequeueAsync(q);
                            if (null != @event)
                            {
                                var handlers = _eventHandlerFactory.GetHandlers(@event.GetType());
                                if (handlers.Count > 0)
                                {
                                    await handlers
                                            .Select(h => h.Handle(@event))
                                            .WhenAll()
                                        ;
                                }
                            }
                        })
                        .WhenAll()
                    ;
            }

            await Task.Delay(1000, stoppingToken);
        }
    }
}

完整的示例代碼可以從https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/AspNetCoreSample 獲取

OverMore

之前在微軟的 EShopOnContainers 項目里又看到類似下面這樣的代碼,在發布事件的時候包裝一層 try … catch 來記錄事件發布日誌,相比之下,本文示例中的這種方式更為簡潔,代碼更清爽

Reference

  • https://www.cnblogs.com/weihanli/p/12941919.html
  • https://www.cnblogs.com/weihanli/p/implement-event-queue.html
  • https://github.com/WeihanLi/WeihanLi.Common
  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/samples/AspNetCoreSample/Startup.cs

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

ansible取出register變量中最長字符串_台中搬家

台中搬家公司費用怎麼算?

擁有20年純熟搬遷經驗,提供免費估價且流程透明更是5星評價的搬家公司

背景

在用ansible撰寫一個etcd恢復的playbook時,有一個操作是獲取etcd啟動時的”initial-cluster”啟動參數,該參數在etcd集群不同節點不一致,需要取出etcd節點啟動參數中最長的作為etcdctl snapshot restore的參數。

[root@tke-init ansible]# cat etcd.hosts 
[etcd]
10.0.32.79
10.0.32.41
10.0.32.97

[snapshot]
10.0.32.79 recoverySnapFile=/alauda/etcd_bak/snap-202005250843.db

[root@tke-init ansible]# cat c.yaml 
---
- name: etcd snapshot recovery
  gather_facts: false
  hosts: all
  tasks:
  - name: get the initial-cluster info
    shell: |+
      cat /etc/kubernetes/manifests/etcd.yaml |grep "initial-cluster="|sed 's/.*initial-cluster=//'
    register: initialCluster

  - debug:
      msg: "{{initialCluster.stdout}}"

如下圖,需要取出圈出的最長的字符串。

實現

shell方式

[root@tke-init ansible]# cat c.yaml 
---
- name: etcd snapshot recovery
  gather_facts: false
  hosts: all
  tasks:
  - name: get the initial-cluster info
    shell: |+
      cat /etc/kubernetes/manifests/etcd.yaml |grep "initial-cluster="|sed 's/.*initial-cluster=//'
    register: initialCluster

  - debug:
      msg: "{{initialCluster.stdout}}"
  
  - name: if the /tmp/a.txt exist,remove it 
    file:
      path: /tmp/a.txt
      state: absent
      force: yes
    run_once: true
    delegate_to: localhost 

  - name: echo the all initialCluster parameter to localhost
    shell: |+
      echo "{{item}}" >>/tmp/a.txt
    with_items:
      - "{{ initialCluster.stdout }}"
    delegate_to: localhost

  - name: get the longest initial-cluster paramaters
    shell:
      cat /tmp/a.txt  |awk '{print length($0),$0}'|sort -k1 -rn|head -1|awk '{print $2}'
    register: maxInitialCluster
    run_once: true
    delegate_to: localhost
  - debug:
      msg: "{{ maxInitialCluster.stdout }}"

執行測試如下

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

台中搬家公司推薦超過30年經驗,首選台中大展搬家

ansible過濾器方式

[root@tke-init ansible]# cat bb.yaml 
---
- name: test
  gather_facts: false
  hosts: all
  tasks:
  - name: get the initial-cluster info
    shell: |+
      cat /etc/kubernetes/manifests/etcd.yaml |grep "initial-cluster="|sed 's/.*initial-cluster=//'
    register: initialCluster

  - set_fact:
       combined_initialCluster: "{{ groups['etcd'] |map('extract',hostvars,['initialCluster','stdout']) |list |join(',')  }}"

  - set_fact:
      final_initialCluster: "{{ combined_initialCluster.split(',')|unique|join(',') }}"

  - debug:
      var: final_initialCluster

執行測試如下

總結

  1. shell方式來說,雖然比較繞,但是更加通用;ansible過濾器方式,其中有一個unique的filter,只適用本次場景中正好有重複列表元素的情況,如果每個節點的register取回的字符串完全不一致,則無法適用。

  2. 取回全部register的字符串組合成一個list后,原本計劃使用max過濾器取出列表中最長的字符串元素,發現max過濾器無法傳遞key參數,而python原生的max方法是支持傳遞key參數的。

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

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

台中搬家公司推薦超過30年經驗,首選台中大展搬家

Shiro (Shiro + JWT + SpringBoot應用)_台中搬家公司

※推薦台中搬家公司優質服務,可到府估價

台中搬鋼琴,台中金庫搬運,中部廢棄物處理,南投縣搬家公司,好幫手搬家,西屯區搬家

Shiro (Shiro + JWT + SpringBoot應用)

目錄

  • Shiro (Shiro + JWT + SpringBoot應用)
    • 1.Shiro的簡介
    • 2.Shiro + JWT + SpringBoot
      • 1.導入依賴
      • 2.配置JWT
      • 3.配置Shiro
      • 4.實現JWTToken
      • 5.實現Realm
      • 6.重寫Filter
      • 7. ShiroConfig
      • 8.登陸
      • 9.@RequiresPermissions

1.Shiro的簡介

Apache Shiro是一種功能強大且易於使用的Java安全框架,它執行身份驗證,授權,加密和會話管理,可用於保護 從命令行應用程序,移動應用程序到Web和企業應用程序等應用的安全。

  1. Authentication 身份認證/登錄,驗證用戶是不是擁有相應的身份;
  2. Authorization 授權,即權限驗證,驗證某個已認證的用戶是否擁有某個權限;即判斷用戶是否能做事情,常見的如:驗證某個用戶是否擁有某個角色。或者細粒度的驗證某個用戶對某個資源是否具有某個權限;
  3. Cryptography 安全數據加密,保護數據的安全性,如密碼加密存儲到數據庫,而不是明文存儲;
  4. Session Management 會話管理,即用戶登錄后就是一次會話,在沒有退出之前,它的所有信息都在會話中;
  5. Web Integration web系統集成
  6. Interations 集成其它應用,spring、緩存框架

從應用程序角度的來觀察如何使用Shiro完成工作:

Subject:主體,代表了當前“用戶”,這個用戶不一定是一個具體的人,與當前應用交互的任何東西都是Subject,如網絡爬蟲,機器人等;即一個抽象概念;所有Subject都綁定到SecurityManager,與Subject的所有交互都會委託給SecurityManager;可以把Subject認為是一個門面;SecurityManager才是實際的執行者;

SecurityManager:安全管理器;即所有與安全有關的操作都會與SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它負責與後邊介紹的其他組件進行交互,如果學習過SpringMVC,你可以把它看成DispatcherServlet前端控制器;

Realm:域,Shiro從從Realm獲取安全數據(如用戶、角色、權限),就是說SecurityManager要驗證用戶身份,那麼它需要從Realm獲取相應的用戶進行比較以確定用戶身份是否合法;也需要從Realm得到用戶相應的角色/權限進行驗證用戶是否能進行操作;可以把Realm看成DataSource,即安全數據源。

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

還在煩惱搬家費用要多少哪?台中大展搬家線上試算搬家費用,從此不再擔心「物品怎麼計費」、「多少車才能裝完」

也就是說對於我們而言,最簡單的一個Shiro應用:

1、應用代碼通過Subject來進行認證和授權,而Subject又委託給SecurityManager;

2、我們需要給Shiro的SecurityManager注入Realm,從而讓SecurityManager能得到合法的用戶及其權限進行判斷。

2.Shiro + JWT + SpringBoot

1.導入依賴
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.1</version>
</dependency>
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.2</version>
</dependency>
2.配置JWT
public class JWTUtil {
    /**
     * 校驗 token是否正確
     *
     * @param token  密鑰
     * @param secret 用戶的密碼
     * @return 是否正確
     */
    public static boolean verify(String token, String username, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("username", username)
                    .build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.info("token is invalid{}", e.getMessage());
            return false;
        }
    }

    public static String getUsername(HttpServletRequest request) {
        // 取token
        String token = request.getHeader("Authorization");
        return getUsername(UofferUtil.decryptToken(token));
    }
    /**
     * 從 token中獲取用戶名
     * @return token中包含的用戶名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            log.error("error:{}", e.getMessage());
            return null;
        }
    }
    
    public static Integer getUserId(HttpServletRequest request) {
        // 取token
        String token = request.getHeader("Authorization");
        return getUserId(UofferUtil.decryptToken(token));
    }
    /**
     * 從 token中獲取用戶ID
     * @return token中包含的ID
     */
    public static Integer getUserId(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return Integer.valueOf(jwt.getSubject());
        } catch (JWTDecodeException e) {
            log.error("error:{}", e.getMessage());
            return null;
        }
    }


    /**
     * 生成 token
     * @param username 用戶名
     * @param secret   用戶的密碼
     * @return token 加密的token
     */
    public static String sign(String username, String secret, Integer userId) {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("alg", "HS256");
            map.put("typ", "JWT");
            username = StringUtils.lowerCase(username);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.create()
                    .withHeader(map)
                    .withClaim("username", username)
                    .withSubject(String.valueOf(userId))
                    .withIssuedAt(new Date())
//                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (Exception e) {
            log.error("error:{}", e);
            return null;
        }
    }
}
3.配置Shiro
4.實現JWTToken

token自己已經包含了用戶名等信息。

@Data
public class JWTToken implements AuthenticationToken {

    private static final long serialVersionUID = 1282057025599826155L;

    private String token;

    private String exipreAt;

    public JWTToken(String token) {
        this.token = token;
    }

    public JWTToken(String token, String exipreAt) {
        this.token = token;
        this.exipreAt = exipreAt;
    }

    @Override
    public Object getPrincipal() {
        return token;
    }

    @Override
    public Object getCredentials() {
        return token;
    }

}
5.實現Realm

自定義實現 ShiroRealm,包含認證和授權兩大模塊。

public class ShiroRealm extends AuthorizingRealm {

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysMenuService menuService;

    // 必須重寫此方法,不然Shiro會報錯
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 只有當需要檢測用戶權限的時候才會調用此方法
     * 授權模塊,獲取用戶角色和權限。
     * @param token token
     * @return AuthorizationInfo 權限信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection token) {
        Integer userId = JWTUtil.getUserId(token.toString());

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        // 獲取用戶角色集
        Set<String> roleSet = roleService.selectRolePermissionByUserId(userId);
        simpleAuthorizationInfo.setRoles(roleSet);

        // 獲取用戶權限集
        Set<String> permissionSet = menuService.findUserPermissionsByUserId(userId);
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

    /**
     * 用戶認證:編寫shiro判斷邏輯,進行用戶認證
     * @param authenticationToken 身份認證 token
     * @return AuthenticationInfo 身份認證信息
     * @throws AuthenticationException 認證相關異常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 這裏的 token是從 JWTFilter 的 executeLogin 方法傳遞過來的,已經經過了解密
        String token = (String) authenticationToken.getCredentials();
        String encryptToken = UofferUtil.encryptToken(token); //加密token
        String username = JWTUtil.getUsername(token); //從token中獲取username
        Integer userId = JWTUtil.getUserId(token);    //從token中獲取userId

        // 通過redis查看token是否過期
        HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
        String ip = IPUtil.getIpAddr(request);
        String encryptTokenInRedis = redisUtil.get(Constant.RM_TOKEN_CACHE + encryptToken + StringPool.UNDERSCORE + ip);
        if (!token.equalsIgnoreCase(UofferUtil.decryptToken(encryptTokenInRedis))) {
            throw new AuthenticationException("token已經過期");
        }

        // 如果找不到,說明已經失效
        if (StringUtils.isBlank(encryptTokenInRedis)) {
            throw new AuthenticationException("token已經過期");
        }

        if (StringUtils.isBlank(username)) {
            throw new AuthenticationException("token校驗不通過");
        }

        // 通過用戶id查詢用戶信息
        SysUser user = userService.getById(userId);

        if (user == null) {
            throw new AuthenticationException("用戶名或密碼錯誤");
        }
        if (!JWTUtil.verify(token, username, user.getPassword())) {
            throw new AuthenticationException("token校驗不通過");
        }
        return new SimpleAuthenticationInfo(token, token, "febs_shiro_realm");
    }
}
6.重寫Filter

所有的請求都會先經過 Filter,所以我們繼承官方的 BasicHttpAuthenticationFilter ,並且重寫鑒權的方法。

代碼的執行流程 preHandle -> isAccessAllowed -> isLoginAttempt -> executeLogin

@Slf4j
public class JWTFilter extends BasicHttpAuthenticationFilter {

    private static final String TOKEN = "Authorization";

    private AntPathMatcher pathMatcher = new AntPathMatcher();

    /**
     * 對跨域提供支持
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
        httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
        // 跨域時會首先發送一個 option請求,這裏我們給 option請求直接返回正常狀態
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            httpServletResponse.setStatus(HttpStatus.OK.value());
            return false;
        }
        return super.preHandle(request, response);
    }
    
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        UofferProperties UofferProperties = SpringContextUtil.getBean(UofferProperties.class);
        // 獲取免認證接口 url 
        // 在application.yml中配置/adminApi/auth/doLogin/**,/adminApi/auth/register/**, ...
        String[] anonUrl = StringUtils.splitByWholeSeparatorPreserveAllTokens(UofferProperties.getShiro().getAnonUrl(), ",");

        boolean match = false;
        for (String u : anonUrl) {
            if (pathMatcher.match(u, httpServletRequest.getRequestURI())) {
                match = true;
            }
        }
        if (match) {
            return true;
        }
        if (isLoginAttempt(request, response)) {
            return executeLogin(request, response);
        }
        return false;
    }

    /**
     * 判斷用戶是否想要登入。
     * 檢測header裏面是否包含Authorization字段即可
     */
    @Override
    protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader(TOKEN);
        return token != null;
    }

    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = httpServletRequest.getHeader(TOKEN); //得到token
        JWTToken jwtToken = new JWTToken(UofferUtil.decryptToken(token)); // 解密token
        try {
            // 提交給realm進行登入,如果錯誤他會拋出異常並被捕獲
            getSubject(request, response).login(jwtToken);
            // 如果沒有拋出異常則代表登入成功,返回true
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    @Override
    protected boolean sendChallenge(ServletRequest request, ServletResponse response) {
        log.debug("Authentication required: sending 401 Authentication challenge response.");
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
//        httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        httpResponse.setCharacterEncoding("utf-8");
        httpResponse.setContentType("application/json; charset=utf-8");
        final String message = "未認證,請在前端系統進行認證";
        final Integer status = 401;
        try (PrintWriter out = httpResponse.getWriter()) {
//            String responseJson = "{\"message\":\"" + message + "\"}";
            JSONObject responseJson = new JSONObject();
            responseJson.put("msg", message);
            responseJson.put("status", status);
            out.print(responseJson);
        } catch (IOException e) {
            log.error("sendChallenge error:", e);
        }
        return false;
    }



}
7. ShiroConfig
@Configuration
public class ShiroConfig {

    @Bean
    public ShiroRealm shiroRealm() {
        // 配置 Realm
        return new ShiroRealm();
    }
    
    // 創建DefaultWebSecurityManager
    @Bean("securityManager")
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 配置 SecurityManager,並注入 shiroRealm
        securityManager.setRealm(shiroRealm());
        return securityManager;
    }
    
    // 創建ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 設置 securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

       	//添加Shiro過濾器
		/**
		 * Shiro內置過濾器,可以實現權限相關的攔截器
		 *    常用的過濾器:
		 *       anon: 無需認證(登錄)可以訪問
		 *       authc: 必須認證才可以訪問
		 *       user: 如果使用rememberMe的功能可以直接訪問
		 *       perms: 該資源必須得到資源權限才可以訪問
		 *       role: 該資源必須得到角色權限才可以訪問
		 */
        
        // 在 Shiro過濾器鏈上加入 自定義過濾器JWTFilter 並取名為jwt
        LinkedHashMap<String, Filter> filters = new LinkedHashMap<>();
        filters.put("jwt", new JWTFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 自定義url規則
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 所有請求都要經過 jwt過濾器
        filterChainDefinitionMap.put("/**", "jwt");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 下面的代碼是添加註解支持
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        // 設置代理類
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);

        return creator;
    }

    /**
     * 開啟aop註解支持
     *
     * @param securityManager
     * @return
     */
    @Bean("authorizationAttributeSourceAdvisor")
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    
    // Shiro生命周期處理器
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

}

8.登陸
    /**
     * 登錄方法
     *
     * @param username 用戶名
     * @param password 密碼
     * @param code     驗證碼
     * @param uuid     唯一標識
     * @return 結果
     */
    @PostMapping("/doLogin")
    public ResultVo login(String username, String password, String code, String uuid, HttpServletRequest request) throws UofferException {

        String verifyKey = Constant.RM_CAPTCHA_CODE_KEY + uuid;
        String captcha = redisUtil.getCacheObject(verifyKey);
        redisUtil.del(verifyKey);

        if (captcha == null) {
            return ResultVo.failed(201, "驗證碼失效");
        }
        if (!code.equalsIgnoreCase(captcha)) {
            return ResultVo.failed(201, "驗證碼錯誤");
        }

        username = StringUtils.lowerCase(username);
        password = MD5Util.encrypt(username, password);

        final String errorMessage = "用戶名或密碼錯誤";
        SysUser user = userManager.getUser(username);

        if (user == null) {
            return ResultVo.failed(201, errorMessage);
        }
        if (!StringUtils.equalsIgnoreCase(user.getPassword(), password)) {
            return ResultVo.failed(201, errorMessage);
        }
        if (Constant.STATUS_LOCK.equals(user.getStatus())) {
            return ResultVo.failed(201, "賬號已被鎖定,請聯繫管理員!");
        }


        Integer userId = user.getUserId();
        String ip = IPUtil.getIpAddr(request);
        String address = AddressUtil.getCityInfo(ip);
        // 更新用戶登錄時間
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLastLoginTime(new Date());
        sysUser.setLastLoginIp(ip);
        userService.updateById(sysUser);


        // 拿到token之後加密
        String sign = JWTUtil.sign(username, password, userId);
        String token = UofferUtil.encryptToken(sign);
        LocalDateTime expireTime = LocalDateTime.now().plusSeconds(properties.getShiro().getJwtTimeOut());
        String expireTimeStr = DateUtil.formatFullTime(expireTime);
        JWTToken jwtToken = new JWTToken(token, expireTimeStr);

        // 將登錄日誌存入日誌表中
        SysLoginLog loginLog = new SysLoginLog();
        loginLog.setIp(ip);
        loginLog.setAddress(address);
        loginLog.setLoginTime(new Date());
        loginLog.setUsername(username);
        loginLog.setUserId(userId);
        loginLogService.save(loginLog);

        saveTokenToRedis(username, jwtToken, ip, address);
        JSONObject data = new JSONObject();
        data.put("Authorization", token);

        // 將用戶配置及權限存入redis中
        userManager.loadOneUserRedisCache(userId);
        return ResultVo.oK(data);
    }
9.@RequiresPermissions

要求subject中必須含有bus:careerTalk:query的權限才能執行方法someMethod()。否則拋出異常AuthorizationException

@RequiresPermissions("bus:careerTalk:query")
public void someMethod() {
}

引用:
https://www.iteye.com/blog/jinnianshilongnian-2018398
https://www.jianshu.com/p/f37f8c295057

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

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

還在煩惱搬家費用要多少哪?台中大展搬家線上試算搬家費用,從此不再擔心「物品怎麼計費」、「多少車才能裝完」

月銷2萬!國產SUV又一爆款誕生了!_網頁設計公司

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

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

5的最低投訴銷量比奪得第一,大幅超越主流合資產品,成為有口皆碑的A級車“品質王”。榮威360憑藉“藍芯”科技在動力總成上的核心優勢,以榮威RX5和榮威360為代表的產品“量價齊收”,還將持續帶動榮威品牌的快速增長。新能源:獲中國汽車界“諾貝爾”獎,勇奪專業賽道“插混王”10月,上汽新能源不僅在技術、整車性能等方面得到了行業和消費者的認可,市場銷量也在不斷攀升。

在榮威RX5強勁熱銷勢頭的帶動下,上汽乘用車10月銷量破4萬,同比激增147%!榮威品牌更是以245%的增速,蟬聯中國品牌增速王!

10月,榮威RX5月銷量首次突破2萬輛,截至目前訂單量已突破10萬輛。第4.5萬輛榮威RX5已於日前在上汽臨港生產基地下線,南京工廠榮威RX5生產線也如期改造完成並將全面投產。榮威RX5的熱銷還帶動了榮威、MG名爵各款車型的銷售,上汽乘用車10月份總銷量超過4萬輛,同比激增147%。

上汽乘用車堅持中高端發展路線,十年磨一劍,通過品質和技術的提升來打造最好的產品。隨着今年“芯動戰略”成果的集中爆發,上汽也正式駛入“品質+銷量”發展階段的“快車道”,引領中國品牌走進品價比時代。

榮威RX5月銷量破2萬 好爸爸聯手領跑市場

10月,榮威RX5銷量突破2萬輛。在榮威RX5熱銷帶動下,上汽榮威品牌從8月同比增長205%,9月增214%,到10月的245%,銷量連續翻番,勢如破竹,帶領上汽乘用車重回發展快車道。爆款SUV榮威RX5上市第三個月銷量即破2萬,還獲得李克強總理親切“接見”,以及工博會工業設計金獎、2017年度德國紅點“中國好設計”榮譽獎、2016“上海市優秀工業設計金獎”等榮譽;榮威360和榮威350組成的“榮威3系”,9月、10月銷量接連破萬,實現了銷量與口碑的雙豐收。

榮威RX5獲工博會工業設計金獎

從上市不到2周互聯網車型訂單破萬,到上市首月交車近萬輛,次月銷量近1.4萬輛,再到第三個月銷量超過2萬輛,榮威RX5的爆款熱銷之勢根本停不下來!作為首款成功突破合資價格區間的中國品牌SUV,真正讓消費者“買得起、用得爽”,成為10-20萬元SUV首選。隨着榮威RX5持續熱賣,勢必將進一步撬動車市格局。

榮威RX5在SUV市場上的大獲全勝,離不開陳虹“爸爸”和馬雲“爸爸”的聯手助攻。在10月的全球首次互聯網汽車拉力賽中,榮威RX5憑藉上汽世界級“藍芯”高效動力科技,以及阿里的互聯網黑科技,創下3.7L/百公里的超低油耗紀錄,刷新SUV節油標準。憑藉互聯網“黑科技”在複雜生活場景中的實際應用,榮威RX5率先開啟了未來交通密碼,為用戶探索追求新生活方式的可能性。

榮威RX5全球首次互聯網汽車拉力賽啟動

不只在SUV市場發力,在家轎市場上,榮威品牌勢頭同樣強勁。上市一周年的榮威360,憑藉全方位高品質和紮實的用戶口碑,累計銷售9萬輛,成為囊括“Carplay車型銷量王”、“品質王”及“A級車節油王”的“三冠王”,更是榮獲德國紅點“中國好設計”唯一汽車類大獎。此前的“千公里一箱油”極限油耗挑戰總決賽中,榮威360一箱油可行駛1496km,創下3.7L/100km的最低油耗紀錄,力證“藍芯”世界級高效動力的領先燃油經濟性。在權威汽車平台《車質網》公布的投訴排行榜中,榮威360以萬分之2.5的最低投訴銷量比奪得第一,大幅超越主流合資產品,成為有口皆碑的A級車“品質王”。

榮威360

憑藉“藍芯”科技在動力總成上的核心優勢,以榮威RX5和榮威360為代表的產品“量價齊收”,

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

還將持續帶動榮威品牌的快速增長。

新能源:獲中國汽車界“諾貝爾”獎,勇奪專業賽道“插混王”

10月,上汽新能源不僅在技術、整車性能等方面得到了行業和消費者的認可,市場銷量也在不斷攀升。

10月28日,中國汽車工業科學技術獎揭曉,上汽新能源憑藉在EDU電驅、HCU電控和ESS電池方面的創新,成為今年插電混動領域唯一獲一等獎的車企,這也是上汽時隔5年再次獲得中國汽車界最高榮譽。中國汽車工業科學技術獎是經國家科委批准,業內公認的最能代表中國汽車科技發展水平的獎項,被譽為中國汽車界“諾貝爾獎”。擁有百餘項國內外專利授權和技術認證,上汽插電混動技術突破了混合動力技術的專利壁壘,成為最先進的新能源汽車動力科技。

榮威e550

得益於上汽世界級新能源科技的運用,榮威e550首次參加中國量產車性能大賽(CCpC),便以總成績第一的表現摘得冠軍,並分別在長距離經濟性、制動性、舒適性等方面共斬獲了6個單項冠軍,充分驗證了上汽新能源領先世界的產品性能,大大增強了消費者的購買信心。

截止10月,上汽新能源今年已累計銷售17474輛,同比大增114%。其中,主銷車型榮威e550共銷售了13600輛,同比增長72%,多次獲得新能源中級車“銷量王”稱號。今年上市的中國首款插電混動高級轎車榮威e950,已連續三個月成為上海B級車銷量冠軍,並成為中國首款月銷過千的新能源B級車。

榮威e950

接下來,上汽新能源還將推出SUV車型,豐富消費者選擇,並引領中高端SUV市場消費趨勢,給消費者提供最智能便捷、最節能環保的出行方案。

MG名爵:前10月同比增長30% 名爵銳騰高性能領跑SUV細分市場

MG名爵10月繼續保持穩步攀升的態勢。今年1-10月,MG名爵全系車型銷量達到58797輛,與去年同比勁增27%!“高性能中級SUV”名爵銳騰更是以全面越級的產品力強勢領跑,同比增長30%。

征戰,不是我們的習慣,而是我們的傳統!作為“高性能中級SUV”,名爵銳騰7月從新疆天山開啟征程,以“十項全能 挑戰巔峰”的高性能姿態全面征服嚴苛複雜的山路環境。得益於上汽世界級“藍芯”動力科技與保時捷專業級底盤調校強強聯手,名爵銳騰從絕壁斷崖到5000米海拔全面制霸,並用自己獨有的方式和態度號召更多年輕人加入到征戰的隊伍中,把自己的愛車真正“開出趣”、綻放年輕的魅力。

名爵銳騰

除了SUV產品的出色表現,高性能風尚中級車MG GT名爵銳行勢頭同樣強勁,1-10月銷量同比增長更是高達61%。今年推出2016款MG GT名爵銳行並新增1.5L車型后,其價格下探至7萬區間,幫助更多年輕消費者實現購車夢想。此外,9月起MG GT名爵銳行的智能娛樂行車系統全面升級,可支持百度CarLife,適配手機的型號更寬泛,名爵銳行也成為首款同時兼容蘋果Carplay和百度CarLife的中級車,全面進入“雙Car”時代。

MG名爵與生俱來的競速基因,讓更多的消費者享受駕控樂趣和汽車生活,綻放獨有的個性魅力,將愛車“開出趣”。即將進入年底收官的關鍵,高性能、高智能、高安全的核心優勢,將帶動MG名爵品牌持續高速增長。

隨着品價比時代的到來,上汽始終堅持品質為王,打造符合時代的最好產品。在“芯動戰略”的整體戰略布局下,上汽乘用車以“藍芯”和“綠芯”兩大技術品牌為支撐,搭載互聯網思維,堅持創新發展,突破傳統局限。未來上汽乘用車還將不斷超越創新,為消費者帶來更多高品質的越級之作。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

9萬級省油耐用到頂點的兩款三廂車 誰最值得買?_如何寫文案

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

什麼是銷售文案服務?A就是幫你撰寫適合的廣告文案。當您需要販售商品、宣傳活動、建立個人品牌,撰寫廣告文案都是必須的工作。

5升發動機最大馬力107匹。最大功率最大扭矩140牛米。陽光最大馬力112匹最大扭矩139牛米,並且兩台車型都搭配CVT的變速器。在實際的主觀加速感受上兩輛車都不怎麼樣。好在動力系統的平順性十分好。並且在油耗方面兩台車的工信部綜合油耗分別為威馳5。

前不久有個粉絲問小編美美,我現在糾結在豐田的威馳和日產的陽光之間,它們都很省油,而且尺寸也不大比較適合家用,價格也算便宜。很適合我這種經濟能力不高的人。可是這兩個車型有差不多的尺寸,同樣都是1.5升發動機和CVT變速箱,也同樣省油。兩個品牌也都不錯,這兩個車讓我十分糾結我到底應該選哪一個比較好呢?

其實我相信有不少人都糾結在這兩款車之間,那麼小編美美就來給你們進行一個分析,看一看哪一個更加值得購買。

對比車型:

豐田威馳 2017款 1.5L CVT創行版

指導價:8.98萬(下文簡稱威馳)

日產陽光 2015款 1.5XE CVT舒適版

指導價:8.98萬(下文簡稱陽光)

外觀

威馳更加好看

從外觀上來說兩個車型的風格可以說有着比較明顯的區別,陽光是屬於那種非常圓潤,在設計元素以及細節上有一些像日產天籟,不過奇怪的比例以及比較小的輪轂這些因素導致陽光看起來不那麼協調,總感覺怪怪的。直白地說,有不少人都覺得陽光長得不好看。

而一向中庸的豐田在威馳的造型設計上也基本遵循的這個理念,它的比例以及設計都比較的均衡,威馳算不上一台很漂亮的小車,它同樣存在着比較高比較窄的缺點,但是威馳看起來比陽光要均衡很多,不會讓人覺得丑。

內飾

威馳設計更有檔次

在內飾設計上陽光多以圓形元素為主打一種輕鬆活潑的內飾設計風格,這樣的設計比較能夠討好女性消費者,但是並不太符合男性消費者的喜好。內飾的用料全部都是硬塑料,做工也只能算是一般般和這個價位的自主車型相比有着不小的差距。

威馳在內飾上則顯得更加的討巧。雖然它的用料也是硬塑料,

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

擁有後台管理系統的網站,將擁有強大的資料管理與更新功能,幫助您隨時新增網站的內容並節省網站開發的成本。

但是它的配色更加豐富,而且車內大量的運用了仿真皮縫線的設計,逼真程度還十分高,你如果不是用手去摸光看上去可能會覺得真的就是皮質的,這也給車內的檔次感增色不少。

空間

半斤八兩

如果你仔細觀察兩個車的話,會發現他們的車廂設計都非常的飽滿。在一個小型車的基礎上卻有這一個大大的肚子,這也是為了極力營造車內空間而做出的考量。這樣的設計帶來的好處則是它們的車內空間無論是頭部還是腿部都十分的寬敞,完全達到了緊湊型轎車的水準,但是兩車都受限於僅僅一米七左右的車身寬度。他們的車內橫向空間只能算是一般般。

動力

初段威馳更好

兩款車型都採用1.5升自然吸氣的發動機,其中豐田威馳的1.5升發動機最大馬力107匹。最大功率最大扭矩140牛米。陽光最大馬力112匹最大扭矩139牛米,並且兩台車型都搭配CVT的變速器。在實際的主觀加速感受上兩輛車都不怎麼樣。好在動力系統的平順性十分好。並且在油耗方面兩台車的工信部綜合油耗分別為威馳5.1升/100公里,陽光5.8升/100公里。如果從省油的角度來考慮的話這兩台車的動力系統也算是十分優秀了。

配置

威馳碾壓陽光

這樣兩個各方面都爭鋒相對的對手,在外觀、內飾、空間和動力方面的表現都不相伯仲,那麼配置就成了它們的關鍵競爭點了。在配置上剛剛完成改款的豐田威馳可以說全面碾壓日產陽光,首先威馳有着15寸的輪轂,而陽光為14寸。而威馳相比陽光多出了

牽引力控制系統

車身穩定控制

上坡輔助

座椅高低調節

後排杯架

后視鏡電動調節

發動機啟停

而陽光僅僅多出行車電腦显示屏這一個配置。因此,在配置上豐田威馳可以說碾壓日產陽光。

總結在外觀上威馳要更加的均衡比陽光耐看很多。在內飾的設計上豐田威馳也要更加的雞賊。雖然用料和配置相差不多,但是豐田在內飾設計上確實玩出了花樣,威馳的整個內飾看上去比陽光要高上一個級別。在空間和動力上兩款車型表現十分接近,而在配置上威馳全面碾壓陽光。因此這次pk的結果非常明確那就是豐田威馳完勝。

不過汽車還是一個感性的產品。因此小編美美也想多談一些對兩款車的看法。這兩款車型小編美美都進行過一定程度的體驗。從家用的角度來講陽光的舒適性要更加的好,主要體現在它的底盤的質感比威馳好一些,而且減震器的阻尼設定也要更加的合理科學。確切的說是豐田威馳有一些顛了,日常乘坐在走爛路的時候,舒適性並不咋地,所以小編覺得如果你是一個十分注重舒適性的人。那麼可能日產陽光會更佳的適合你。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

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

銷售文案是什麼?A文案是廣告用的文字。舉凡任何宣傳、行銷、販賣商品時所用到的文字都是文案。在網路時代,文案成為行銷中最重要的宣傳方式,好的文案可節省大量宣傳資源,達成行銷目的。

僅7.99萬起的美系A級三廂車 車主們想吐槽?_網頁設計公司

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

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

5L 自動欣尚版裸車價:10。99萬元滿意的地方:前臉的造型很帥,尤其是日行燈。內飾配色搭配的很漂亮,很符合年輕人的口味。空間算大把,反正一家五口人坐着挺舒服的,隔音還算不錯。配置對於家用車較為齊全,在這個價位上該有的基本都有。

如果你預算不夠,但是很鍾情美系車,想買科魯茲但是只能買到低配,配置稍微低了些,那麼你可以考慮下科沃茲,科魯茲的最低配價格就可以買到科沃茲的頂配。至於這輛車如何,看看車主怎麼說。

上汽通用雪佛蘭-科沃茲

指導價:7.99-10.99萬

車身尺寸

長*寬*高:4544*1779*1467mm

軸距:2600mm

動力匹配

1.5L 113馬力 L4 + 5擋手動/6擋手自一體

車主一

購買車型:2016款 1.5L 自動欣悅版

裸車價:9.99萬元

滿意的地方:外觀斯文中帶了野性,很符合年輕人胃口,前臉的造型滿分。內飾整體設計的還是不錯的,儀錶盤的設計很動感。空間較寬敞,175cm的身高不用調節座椅都不會覺得窄,後排中間底盤凸起的不高。動力上家用還是比較足夠的,操控感不錯,电子助力的轉向很舒適,剎車很給力,踩一點就有反應,對加速和超車增加不少信心。

不滿意的地方:尾部的設計有些丑,尾燈感覺像是被吃掉一截。內飾全是硬塑料。后扭力梁是硬傷。

車主二

購買車型:2016款 1.5L 自動欣尚版

裸車價:10.99萬元

滿意的地方:前臉的造型很帥,尤其是日行燈。內飾配色搭配的很漂亮,很符合年輕人的口味。空間算大把,反正一家五口人坐着挺舒服的,隔音還算不錯。配置對於家用車較為齊全,

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

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

在這個價位上該有的基本都有。轉向很精準,指哪打哪,底盤對於小顛簸的過濾性還不錯。油耗比滿意,提到現在跑了500公里,油耗6.5L,跑完磨合期估計會更低。

不滿意的地方:動力有點弱,起步較肉。車前沒有雷達,對於新手來說是硬傷,中控硬塑料太多,全部都是。

總結:科沃茲可以說是科魯茲“低”一級的車型,科沃茲的頂配也只能買到科魯茲的低配車型,這對於預算不多,但是對雪佛蘭的車型興趣的朋友,科沃茲就是不錯的選擇。科沃茲手動擋和自動擋的低配置配置很“素”,中配以上車型會豐富不少,價格也在10萬內,性比價還算可以。對於合資車在這個價位上的用料,自然不用想有多好,但是在造型設計彌補了這一點,至少視覺效果是挺不錯的。科沃茲定位就是一輛家用車,1.5L發動機的動機就不要想有多強勁,家用是足夠的。總體而言,想要美系合資車,預算不多,適合年輕人,科沃茲是不錯的選擇,配置,空間都屬於中上水平。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

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

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

7-8萬的國貨小型SUV 這些車型的競爭力最強!_網頁設計

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

6L比較合適,因為開自動擋的車子,馬力小了會很難受的。雖然新款的S3最低配車型沒有ESp,但是考慮到6。58萬元的售價也勉強可以原諒,從次低配開始有ESp。瑞風S3的性能算是比較穩定,質量表現不錯,月銷量一直保持在較高的水平。

七萬左右,最多只能買個捷達、致炫、K2之類的小車,但是如果用這些錢買自主車,那就可以買到不錯的車子,而且都是大家喜歡的SUV車型。

奇瑞汽車-瑞虎3

瑞虎3的車身尺寸為4420*1760*1670mm,軸距為2510mm。在售的瑞虎3不是全新的車型,而是在老款的基礎之上改進而來的。所以外觀方面變化不是很大,僅僅在細節部位有一些變化。從外觀來看,瑞虎造型比較硬派,像是一款正兒八經的越野車,但是如果你真的開着瑞虎3去越野了,那麼半路肯定會“跪”的,不要指望它能越野,它只是一款極其普通的城市SUV。

瑞虎3的動力系統為1.6L 126馬力+5擋手動/CVT,動力系統比較簡單,但是選擇起來就比較好選擇了。不過即便是最低配的瑞虎3,配置也不會馬虎的,ESp、上坡輔助、后視鏡電動調節都成了標配,不過次低配的性價比顯然更高,價格只比低配貴了幾千,但是卻多出了胎壓監測裝置、電動天窗、真皮方向盤、仿皮座椅、中控台彩色大屏、藍牙等。至於大家關注的油耗問題,瑞虎3手動擋百公里油耗為8.6L左右,自動擋為9.5L左右。

江淮汽車-瑞風S3

新款瑞風S3的車身尺寸分別為4345*1765*1615mm、4345*1765*1640mm,

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

軸距同為2560mm。相比較老款的S3,新款的S3的前臉部分變化比較大,主要是車頭換了新的車標,至於到底好不好看,這就要看大家的喜好了。

瑞風S3動力系統為1.5L 113馬力/1.6L 120馬力+6擋手動/CVT,其中1.5L車型推薦手動擋,想買自動擋最好還是上1.6L比較合適,因為開自動擋的車子,馬力小了會很難受的。雖然新款的S3最低配車型沒有ESp,但是考慮到6.58萬元的售價也勉強可以原諒,從次低配開始有ESp。瑞風S3的性能算是比較穩定,質量表現不錯,月銷量一直保持在較高的水平。也是一款值得推薦小型SUV。

長安汽車-長安CS35

長安CS35的車身尺寸為4160*1810*1670mm,軸距為2560mm。CS35的外觀看起來比較時尚,但是長度只有區區的4.16米,同級別的車子長度都達到了4.3米左右,因為CS35尾部的設計感覺有點短小,如果能再加長一點就好了。

CS35動力系統為1.6L 125馬力+5擋手動/4擋手自一體,1.5T 156馬力+5擋手動,剛才還在想小型SUV怎麼沒有帶渦輪的呢?這不,CS35就上了1.5T的發動機,最大馬力156馬力,駕駛起來動力十足,非常輕快,手動擋換擋很乾脆,吸入感很強,操控不錯。不過CS35的價格不是很實在,配置也不算高,手動豪華型 國IV(8.29萬)車型才開始有ESp,不過不錯的駕乘感受為CS35加分不少。其中1.6L車型手動擋百公里油耗為8L左右,自動擋為9L左右。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

10萬就可以輕鬆入手中型SUV 竟然還帶7座_貨運

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

採用全黑的內飾配色,大尺寸的中控屏非常醒目,整車質感良好,电子駐車、無鑰匙進入/啟動、車身穩定系統、倒車影像等配置比較齊全。儲物空間方面非常豐富,如中控台下方掏空的設計就非常方便放些零碎的東西,2780mm的軸距,帶來的是非常寬敞的空間感受,頭部、腿部空間都有很多餘量。

眾泰汽車-眾泰T600

指導價:7.98-14.98萬

外觀設計方面,眾泰T600給人很大氣的感覺,與途銳有着極其相似的前臉使它看起來一點都不陌生,尾部的造型圓潤不失動感,雙出的排氣管動感十足;內飾整體布局簡潔大方,仿木飾板和銀色飾條的搭配看起來很得體,6安全氣囊、胎壓監測、無鑰匙進入/啟動、自動駐車、倒車影像、自動頭燈等配置應有盡有;2807mm的軸距在同級別中佔有優勢,乘坐舒適度良好,儲物空間表現中規中矩,滿足日常使用;動力提供了1.5T(最大功率162馬力)/2.0T(最大功率190馬力)兩種車型選擇,搭配5擋手動或着6擋雙離合變速箱,動力響應足夠快,底盤的調校偏向舒適。

東風小康-東風風光580

指導價:7.29-9.99萬

風光580可謂是一款網紅級別的車型,外形設計較為動感,車身線條流暢優雅,三條鍍鉻格柵搭配大尺寸的六邊形進氣格柵,力量感十足,雙色多幅鋁合金輪轂與其時尚的外觀很般配;採用全黑的內飾配色,大尺寸的中控屏非常醒目,整車質感良好,

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

电子駐車、無鑰匙進入/啟動、車身穩定系統、倒車影像等配置比較齊全;儲物空間方面非常豐富,如中控台下方掏空的設計就非常方便放些零碎的東西,2780mm的軸距,帶來的是非常寬敞的空間感受,頭部、腿部空間都有很多餘量;1.5T發動機最大功率150馬力,搭配6擋手動或者CVT變速器,動力儲備較為充足,由於車身重心較高的原因,過一些較大顛簸路面時,晃動感會比較大。

長安汽車-長安CX70

指導價:6.89-8.49萬

長安CX70的外觀原創度還是蠻高的,車身看起來很粗獷、硬朗,但車身側面難免會給人一種麵包車的感覺,接近角23.5度,離去角25度,最小離地間隙達到190mm,通過性表現出色;內飾布局規整協調,橙黑雙色的搭配看起來很有活力,中控屏與空調控制系統集成在一起,取消了物理按鍵,非常有特斯拉大屏的那種檔次感,右側全景影像系統便利性很強;CX70的車身高度達到了1750mm,所以頭部空間非常寬敞,採用2+3+2的座椅布局,第三排座椅支持翻折,擴展性強;全系採用1.6L(最大功率117馬力)+5擋手動變速箱的動力組合,滿足日常城市道路使用,而且懸架支撐性好,期待渦輪增壓車型和自動擋的出現。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

每天跑100公里 選這些大氣B級車准沒錯!_網頁設計公司

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

同時,這款速派要喝95號汽油。話雖如此,速派的底盤濾震效果還是杠杠的,對付城區里的小顛簸總能有條不紊地過濾掉。遇到特別爛的路,則會讓你感覺一種帶有厚實感的硬度。配置上,這款速派就有不少亮點,不僅配了胎壓監測,還有自動駐車+电子手剎這對黃金組合,另外還可以選裝電動天窗和發動機啟停。

現在B級車市場的選擇琳琅滿目,為了滿足每天往返市區與郊區的路程,該如何選擇一款符合自己心意的B級車呢?下面編者我就給大家介紹幾款省心又好開的B級車。

廣汽豐田-凱美瑞

2016款 2.0E 十周年紀念精英版

指導價:18.78萬

優惠幅度:2.5萬元左右(僅供參考)

編者點評:

凱美瑞作為一款久歷沙場的車系,各項技術都比較穩定。這款2.0L車型的綜合油耗為8.7L左右,算是比較省油的。現在這款車終端也能有2.5萬元左右的優惠,讓步也夠大的。

一直以來,凱美瑞給人的感覺就是中庸,無論是外觀,還是內飾設計,都給人一種四平八穩,缺乏亮點的感覺。不過,也正是這樣的設計,得到了不少成熟人士的認可。

動力總成上,2.0L自然吸氣發動機配6擋手自一體變速箱,最大輸出167馬力和199牛米。實際動力表現不錯,換擋平順度高,發動機的運轉聲音優雅。但是,在全負荷運轉下,發動機會有點吃力。底盤可過濾大部分路面的顛簸,但是遇到大坑窪時,還是容易露餡。

保養方面,由於官方在6萬公里內免費為車主進行基礎保養,所以最後的保養也僅為3594元。作為一輛B級車來說,這個價格完全可以接受。

上汽大眾斯柯達-速派

2016款 280TSI DSG前行版

指導價:17.98萬

優惠幅度:2.5萬元左右(僅供參考)

編者點評:

雖然斯柯達是大眾的小弟,但是大眾最近把不少新技術都下放給了這位小弟。所以,鍾愛德系的人不妨選一輛斯柯達,畢竟斯柯達的品牌溢價也沒有大眾那麼高。

動力總成上,1.4T的EA211發動機+7速DCT,最大輸出150馬力和250牛米。不過,最大扭矩到3000轉就開始衰減,明顯偏早,

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

而且發動機的噪音偏大,影響乘車質感。同時,這款速派要喝95號汽油。

話雖如此,速派的底盤濾震效果還是杠杠的,對付城區里的小顛簸總能有條不紊地過濾掉。遇到特別爛的路,則會讓你感覺一種帶有厚實感的硬度。

配置上,這款速派就有不少亮點,不僅配了胎壓監測,還有自動駐車+电子手剎這對黃金組合,另外還可以選裝電動天窗和發動機啟停。除此以外,還有氙氣大燈,8-9個喇叭的揚聲器,行車電腦显示屏和后駐車雷達。

東風悅達起亞-起亞K5

2016款 2.0L 自動LUX

指導價:17.58萬

優惠幅度:3.5萬左右(僅供參考)

編者點評:

K5的設計可以說越來越前衛,也越來越能吸引年輕消費者,同時優惠幅度又足夠大。油耗上,這款2.0L車型的百公里綜合油耗為8.9L,算是比較不錯的。

K5搭載了2.0L自然吸氣發動機+6擋手自一體變速箱,最大輸出161馬力和193牛米,這個數據也只能說是中規中矩,開起來平順,輸出線性。K5的底盤濾震比較有韌性,可以帶給駕駛員良好的操控性。

配置上也頗有亮點,首先是18寸的輪胎規格加上全尺寸備胎足夠厚道。除此,還有無鑰匙進入與啟動,感應後備廂,倒車視頻影像和后視鏡電動摺疊。如此豐富的配置才對得上韓系車的名號。

編者總結:

這三款車都是有各自顯著特點的車。首先,凱美瑞雖然是一款偏中庸的車,但是如果一台車各方面都中庸的話,那中庸就是它的特點。凱美瑞應該是屬於那種久處不厭的車子,就算開久了,也不會有什麼大的問題煩擾你。

速派是德系的代表,我覺得它能代表大眾的一部分特性,但是品牌溢價又不會有大眾那麼高。這對於那些純粹想體會一下德系車品質的消費者來說,是個很好的選擇。況且,速派亦是MQB平台的產物,跟邁騰和帕薩特品質不會差太遠,差的只是一個標誌。

K5則在大打配置牌,再配合上那運動的外觀確實能吸引不少年輕消費者的目光。同時,K5也是這幾款車中優惠最大的。誠然,K5在机械質感上與日系和德系的對手比還略遜一籌,不過,它也似乎找到了彎道超車的可能。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單