1. 程式人生 > >【Shiro】Shiro從小白到大神(三)-許可權認證(授權)

【Shiro】Shiro從小白到大神(三)-許可權認證(授權)

本節講許可權認證,也就是授權
基於角色的訪問控制和基於許可權的訪問控制的小例項
以及註解式授權和JSP標籤授權詳解

許可權認證

許可權認證核心要素

許可權認證,也就是訪問控制,即在應用中控制誰能訪問哪些資源
在許可權認證中,最核心的三個要素是:許可權,角色和使用者 (資源也算一個要素,但不是最核心的)
許可權,即操作資源的 許可權,比如訪問某個頁面,以及對某個模組的資料的新增,修改,刪除,檢視的權利(整合以後,其實就是一些對URL請求的許可權)
角色,是許可權的集合,一種角色可以包含多種許可權(將許可權賦給角色)
使用者,在Shiro中,代表訪問系統的使用者,即Subject(將角色賦給使用者)
英文好的,可以去看官方文件介紹:

http://shiro.apache.org/authorization.html

授權

—-基於角色的訪問控制

首先配置ini檔案:

[users]
;基於角色的訪問控制的配置檔案
chx=123456,role1,role2
;加角色,密碼後面是擁有的角色
jack=123456,role1

測試類

package cn.chenhaoxiang.shiro;

import cn.chenhaoxiang.common.ShiroUtils;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
import
org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; /** * 基於角色的訪問控制 */ public class RoleTest { private static Logger logger = LoggerFactory.getLogger(RoleTest.class); /** * hasRole(String roleName) Returns true if the Subject is assigned the specified role, false otherwise. * hasRoles(List<String> roleNames) Returns a array of hasRole results corresponding to the indices in the method argument. Useful as a performance enhancement if many role checks need to be performed (e.g. when customizing a complex view) * hasAllRoles(Collection<String> roleNames) Returns true if the Subject is assigned all of the specified roles, false otherwise. * hasRole 判斷是否擁有某個角色 * * hasRoles 判斷擁有某個角色 返回的是boolean[] 用來高效判斷對應角色擁有 * hasAllRoles 判斷擁有所有角色 擁有傳入的全部角色的話,才返回true * */
@Test public void testHasRole(){ Subject subject = ShiroUtils.login("classpath:shiro_role.ini","chx","123456"); logger.info(subject.hasRole("role1")?"有role1這個角色":"沒有role1這個角色"); logger.info(subject.hasRole("role2")?"有role2這個角色":"沒有role2這個角色"); Subject subject2 = ShiroUtils.login("classpath:shiro_role.ini","jack","123456"); logger.info(subject2.hasRole("role1")?"有role1這個角色":"沒有role1這個角色"); logger.info(subject2.hasRole("role2")?"有role2這個角色":"沒有role2這個角色"); // hasRoles 判斷擁有某個角色 返回的是boolean[] 用來高效判斷對應角色擁有 boolean[] results = subject.hasRoles(Arrays.asList("role1","role2","role3")); logger.info(results[0]?"有role1這個角色":"沒有role1這個角色"); logger.info(results[1]?"有role2這個角色":"沒有role2這個角色"); logger.info(results[2]?"有role2這個角色":"沒有role3這個角色"); //hasAllRoles 判斷擁有所有角色 擁有傳入的全部角色的話,才返回true logger.info(subject.hasAllRoles(Arrays.asList("role1","role2"))?"有role1和role2這兩個個角色":"role1,role2這兩個角色不全部有"); subject.logout();//退出 } /** * CheckRole */ @Test public void testCheckRole(){ Subject subject = ShiroUtils.login("classpath:shiro_role.ini","chx","123456"); subject.checkRole("role1");//沒有返回值 //subject.checkRole("role3");//沒有這個角色會丟擲異常 //org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role211] //checkRoles(Collection<String> roleNames) subject.checkRoles(Arrays.asList("role1","role2")); //subject.checkRoles(Arrays.asList("role1","role2","role3"));//沒有全部角色會丟擲異常 //org.apache.shiro.authz.UnauthorizedException: Subject does not have role [role3] //checkRoles(String... roleNames)和checkRoles(Collection<String> roleNames)意思一樣,傳入的引數型別不同 subject.checkRoles("role1","role2"); subject.logout();//退出 } }

演示結果自己跑一遍就出來啦

—-基於許可權的訪問控制

配置ini檔案:

[users]
;基於許可權的訪問控制的配置檔案
chx=123456,role1,role2
;加角色,密碼後面是擁有的角色
jack=123456,role1
[roles]
;不判斷角色,直接判斷許可權
role1=user:select
;role1擁有select許可權 這裡的user:select許可權名字是自己定義的
role2=user:add,user:update,user:delete
;許可權無非就是增刪改查

測試類:

package cn.chenhaoxiang.shiro;

import cn.chenhaoxiang.common.ShiroUtils;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 基於許可權的訪問控制
 */
public class PermissionTest {

    private static Logger logger = LoggerFactory.getLogger(PermissionTest.class);

    /**
     * isPermitted(Permission p)  isPermitted(String str)  如果是擁有訪問某個資源的許可權,返回true  單個許可權判斷
     *
     * isPermitted(String... var1);  分別判斷多個許可權  返回boolean[]
     *
     * isPermittedAll(String... var1);  擁有所有許可權才返回true
     */

    @Test
    public void testIsPermitted(){
        //Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","chx","123456");
        Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","jack","123456");
        logger.info(subject.isPermitted("user:select")?"有user:select許可權":"沒有user:select許可權");
        logger.info(subject.isPermitted("user:update")?"有user:update許可權":"沒有user:update許可權");

        boolean results[] = subject.isPermitted("user:select","user:update","user:delete");
        logger.info(results[0]?"有user:select許可權":"沒有user:select許可權");
        logger.info(results[1]?"有user:update許可權":"沒有user:update許可權");
        logger.info(results[2]?"有user:delete許可權":"沒有user:delete許可權");

        logger.info(subject.isPermittedAll("user:select","user:update")?"有user:select和user:update許可權":"user:select和user:update許可權不全有");

        subject.logout();//退出
    }


    /**
     *
     * checkPermission(String var1)  沒有這一個許可權就丟擲異常
     * checkPermissions(String... var1)  沒有這些許可權就丟擲異常
     */
    @Test
    public void testCheckPermitted(){
        //Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","chx","123456");
        Subject subject = ShiroUtils.login("classpath:shiro_permission.ini","jack","123456");

        subject.checkPermission("user:select");//檢查是否有某個許可權  沒有許可權則丟擲異常
        //subject.checkPermission("user:delete");//org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [user:delete]

        subject.checkPermissions("user:select","user:update");

        subject.logout();//退出
    }
}

講了幾個org.apache.shiro.subject.Subject的函式。
其實官方文件都有介紹的

註解式授權

首先你的Java版本5+才能整合shiro的註解

RequiresAuthentication註解

RequiresAuthentication註解需要在當前會話中對當前的Subject進行身份驗證,以便訪問或呼叫該註解的類/例項/方法。
也就是要求當前Subject已經在當前的Session中被驗證通過才能被訪問或呼叫
比如:

@RequiresAuthentication //判斷驗證有沒有通過
public void updateAccount(Account userAccount) {
    //this method will only be invoked by a
    //Subject that is guaranteed authenticated
    ...
}

基本等同於下面的程式碼:

public void updateAccount(Account userAccount) {
    if (!SecurityUtils.getSubject().isAuthenticated()) {
        throw new AuthorizationException(...);
    }

    //Subject is guaranteed authenticated here
    ...
}

RequiresGuest註解

要求當前的Subject是一個’guest’(遊客),也就是說,必須是在之前的session中沒有被驗證或被記住才能被訪問和呼叫
例如:

@RequiresGuest
public void signUp(User newUser) {
    //this method will only be invoked by a
    //Subject that is unknown/anonymous
    ...
}

基本等價於下面的程式碼:

public void signUp(User newUser) {
    Subject currentUser = SecurityUtils.getSubject();
    PrincipalCollection principals = currentUser.getPrincipals();
    if (principals != null && !principals.isEmpty()) {
        //known identity - not a guest:
        throw new AuthorizationException(...);
    }

    //Subject is guaranteed to be a 'guest' here
    ...
}

RequiresPermissions註解

RequiresPermissions註解要求當前Subject允許一個或多個許可權來執行帶註釋的方法。
也就是說,必須有這個許可權才能訪問
例如:

@RequiresPermissions("account:create") //必須有account:create許可權,多個許可權之間用逗號隔開
public void createAccount(Account account) {
    //this method will only be invoked by a Subject
    //that is permitted to create an account
    ...
}

基本等價於:

public void createAccount(Account account) {
    Subject currentUser = SecurityUtils.getSubject();
    if (!subject.isPermitted("account:create")) {
        throw new AuthorizationException(...);
    }

    //Subject is guaranteed to be permitted here
    ...
}

RequiresRoles註解

RequiresRoles註解要求當前Subject擁有所有指定的角色。如果它們沒有所有的角色,則不會執行該方法,並丟擲AuthorizationException

例如:

@RequiresRoles("administrator")
public void deleteUser(User user) {
    //this method will only be invoked by an administrator
    ...
}

基本等同於以下程式碼:

public void deleteUser(User user) {
    Subject currentUser = SecurityUtils.getSubject();
    if (!subject.hasRole("administrator")) {
        throw new AuthorizationException(...);
    }

    //Subject is guaranteed to be an 'administrator' here
    ...
}

RequiresUser註解

RequiresUser註解 需要當前的Subject是一個應用程式的使用者 才能被所註解的類/例項/方法訪問或者呼叫。
一個”應用程式使用者”被定義一個擁有已知身份,或在當前session中通過驗證被確認,或者在之前的session中的”RememberMe”服務被記住
也就是說,必須是某個使用者

例如:

@RequiresUser
public void updateAccount(Account account) {
    //this method will only be invoked by a 'user'
    //i.e. a Subject with a known identity
    ...
}

基本等同於下面程式碼:

public void updateAccount(Account account) {
    Subject currentUser = SecurityUtils.getSubject();
    PrincipalCollection principals = currentUser.getPrincipals();
    if (principals == null || principals.isEmpty()) {
        //no identity - they're anonymous, not allowed:
        throw new AuthorizationException(...);
    }

    //Subject is guaranteed to have a known identity here
    ...
}

JSP標籤授權

必須新增shiro-web.jar

在jsp頁面中引入:

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

guest標籤

使用者沒有身份驗證時顯示相應資訊,即遊客訪問資訊
例如:

<shiro:guest>
    Hi there!  Please <a href="login.jsp">Login</a> or <a href="signup.jsp">Signup</a> today!
</shiro:guest>

在這裡標籤內的文字,如果使用者沒有登入才會顯示出來,也就是遊客

user標籤

只有在當前Subject被認為是“使用者”時,使用者標記才會顯示其包裝內容。
在這個上下文中,“使用者”被定義為一個具有已知身份的主題,要麼是成功的身份驗證,要麼是來自“記住我”的服務。
注意,這個標記與經過身份驗證的標記有語義上的不同,它比這個標記更加嚴格。
例如:

<shiro:user>
    Welcome back John!  Not John? Click <a href="login.jsp">here<a> to login.
</shiro:user>

user標籤和guest標籤邏輯相反

authenticated標籤

僅噹噹前使用者在當前會話中成功驗證時才顯示正文內容。
它比“使用者”標籤更具限制性。它在邏輯上與“notAuthenticated”標記相反。
只有在當前Subject在當前會話中成功驗證的情況下,經過身份驗證的標記才會顯示其包裝內容。
它是一個比使用者更嚴格的標記,用來保證敏感工作流中的標識。也就是說,通過記住我登入的無法訪問到!!!
例如:

<shiro:authenticated>
    <a href="updateAccount.jsp">Update your contact information</a>.
</shiro:authenticated>

notAuthenticated標籤

如果當前Subject在當前會話中尚未成功驗證,則未驗證標記將顯示其包裝內容。
也就是使用者沒有身份驗證通過,即沒有呼叫Subject.login進行登入,包括記住我自動登入的也屬於未進行身份驗證這個notAuthenticated標籤!

例如:

<shiro:notAuthenticated>
    Please <a href="login.jsp">login</a> in order to update your credit card information.
</shiro:notAuthenticated>

principal標籤

輸出使用者資訊,會呼叫toString()方法
例如:

Hello, <shiro:principal/>, how are you today?

相當於呼叫以下程式碼:

Hello, <%= SecurityUtils.getSubject().getPrincipal().toString() %>, how are you today?
通過型別

如果你不想獲取所有的,比如在使用者名稱和使用者id之間,我想獲取使用者id,可以通過下面這種方式:

User ID: <principal type="java.lang.Integer"/>

等同於:

User ID: <%= SecurityUtils.getSubject().getPrincipals().oneByType(Integer.class).toString() %>
通過屬性名

但是,當遇到複雜的情況時,上面的就不行了,畢竟可能不止一個Integer,這個時候就可以通過屬性名了。
通過getter方法獲取的
例如:

Hello, <shiro:principal property="firstName"/>, how are you today?

相當於下面的程式碼:

Hello, <%= SecurityUtils.getSubject().getPrincipal().getFirstName().toString() %>, how are you today?

或者說,可以結合type屬性:

Hello, <shiro:principal type="com.foo.User" property="firstName"/>, how are you today?

也就是如下程式碼的邏輯:

Hello, <%= SecurityUtils.getSubject().getPrincipals().oneByType(com.foo.User.class).getFirstName().toString() %>, how are you today?

hasRole標籤

只有噹噹前Subject被分配指定角色時,hasRole標記才會顯示其包裝內容

例如:

<shiro:hasRole name="administrator">
    <a href="admin.jsp">Administer the system</a>
</shiro:hasRole>

lacksRole標籤

如果當前Subject沒有分配指定的角色,則將顯示其包裝內容。

<shiro:lacksRole name="administrator">
    Sorry, you are not allowed to administer the system.
</shiro:lacksRole>

lacksRole標籤與hasRole標籤的邏輯相反。

hasAnyRole標籤

如果當前Subject從一個由逗號分隔的角色名稱列表中具有了任一指定的角色,那麼hasAnyRole標記將顯示其包裝內容。

<shiro:hasAnyRoles name="developer, project manager, administrator">
    You are either a developer, project manager, or administrator.
</shiro:hasAnyRoles>

只要有其中一個角色,即顯示主體內容

hasPermission標籤

如果當前Subject有許可權則顯示其包裝的內容

<shiro:hasPermission name="user:create">
    <a href="createUser.jsp">Create a new User</a>
</shiro:hasPermission>

lacksPermission標籤

如果當前Subject沒有該許可權則顯示其包裝的內容

<shiro:lacksPermission name="user:delete">
    Sorry, you are not allowed to delete user accounts.
</shiro:lacksPermission>

lacksPermission標籤與hasPermission標籤的邏輯相反

深入理解Apache Shiro的Permissions

萬用字元的許可權

單個許可權: 直接起一個字串名即可

例如: queryPrinter許可權-查詢許可權

subject.isPermitted("queryPrinter")

基本等同於:

subject.isPermitted( new WildcardPermission("queryPrinter") )

第二種方式基本不用,用第一種方式即可

多個許可權: 萬用字元許可權支援多個級別或部分的概念。

下面使用”:”用於分隔許可權字串下一部分的特殊字元。

printer:query
printer:print
printer:manage

即可配置多個許可權

也可以用多值來配置:

printer:print,query

驗證查詢許可權:

subject.isPermitted("printer:query")

單個資源的所有許可權

比如我們有這些許可權:

printer:query,print,manage

相當於:

printer:*

使用第二種方法使用萬用字元比顯式地列出動作要更好,因為如果以後嚮應用程式添加了一個新操作,則不需要更新在該部分中使用萬用字元的許可權。

所有資源的某個許可權

還可以在萬用字元許可權字串的任何部分使用萬用字元令牌

*:view

所有資源的view許可權
也就是說對“foo:view”(或其他的:view)的任何許可權檢查將返回true

例項級別的許可權控制

萬用字元許可權的另一個常見用法是建立例項級訪問控制列表。
在這個許可權中,您將使用三個部分——第一個是域,第二個是動作,第三個是被執行的例項(標識)。

單個例項的單個許可權

printer:query:lp7200
printer:print:epsoncolor

比如你擁有printer的query許可權,印表機的id為lp7200,也就是擁有這類printer的query許可權

如果您將這些許可權授予使用者,那麼它們就可以在特定的例項上執行特定的行為。然後你可以在程式碼中做一個檢查:

if ( SecurityUtils.getSubject().isPermitted("printer:query:lp7200") {
    // Return the current jobs on printer lp7200 }
}

所有例項的單個許可權

printer:print:*

也就是說,具有所有printer的print許可權,相當於前面的單個資源的多個許可權

所有例項的所有許可權

printer:*:*

單個例項的所有許可權

printer:*:lp7200

單個例項的多個許可權

printer:query,print:lp7200

query和print之間用逗號隔開
在實際開發中,基本上用不到例項級別的許可權控制

關於許可權分配的最後一件事是:末尾丟失的部分意味著使用者可以訪問與該部分對應的所有值。換句話說,

printer:print
就相當於:
printer:print:*
printer 
單個許可權相當於
printer:*:*

但是注意!

printer:lp7200printer:*:lp7200
是不同的!!!

因為這不是末尾的*

檢查許可權

雖然許可權分配使用萬用字元構造相當多(“printer:*”=列印到任何printer),但在執行時的許可權檢查應該始終基於可能的最特定的許可權字串。
比如:如果使用者有一個使用者介面,他們想要列印一個文件到lp7200印表機,你應該檢查使用者是否允許執行這個程式碼

if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
    //print the document to the lp7200 printer }
}

這個檢查非常具體,並且明確地反映了使用者在那個時候正在嘗試做什麼。
但是,如下程式碼是不對的:

if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
    //print the document }
}

因為第二個示例說“您必須能夠列印到任何印表機,以便執行以下程式碼塊”。但請記住,“printer:print”等同於“printer:print:*”!

因此,這是一個不正確的檢查。
如果當前使用者沒有能力列印到任何印表機,但他們確實有列印的能力,比如lp7200和epsoncolor印表機。
然而,上面的第二個例子永遠不會允許他們列印到lp7200印表機,即使他們已經獲得了這種能力!

因此,經驗法則是在執行許可權檢查時使用最特殊的許可權字串。
當然,如果您真的只想執行程式碼塊,如果使用者被允許列印到任何印表機(可能),那麼第二個方法可能是應用程式中的另一個有效的檢查。
您的應用程式將決定什麼檢查是有意義的,但是一般來說,越具體越好。

為什麼執行時許可權檢查應該儘可能具體,但是許可權分配可以更通用一些呢?
這是因為許可權檢查是由隱含邏輯計算的,而不是平等檢查。

也就是說,如果使用者被分配給”user:“許可權,這意味著使用者可以執行”user:view”操作。字串”user:“顯然不等於”user:view”,但前者暗示後者。”user:*”描述了由”user:view”定義的功能的超集。

為了支援隱含規則,所有許可權都被翻譯到實現org.apache.shiro.authz的物件例項的許可權介面中。
這就是說,隱含邏輯可以在執行時執行,而且隱含邏輯通常比簡單的字串等式檢查更復雜。
本文件中描述的所有萬用字元行為實際上都是由org.apache.shiro.authz.permission.WildcardPermission類實現

下面是一些萬用字元的許可權字串,它顯示了訪問的含義:

user:*

暗指還能刪除使用者的能力:

user:delete

但是:

user:*:12345

也就是說,還可以使用例項12345更新使用者帳戶:

user:update:12345
printer
暗示了印表機的任何功能,比如:
printer:print

授權流程

授權其實就是檢視有沒有許可權,有就授權給它

授權步驟:

Step 1: Application or framework code invokes any of the Subject hasRole*, checkRole*, isPermitted*, or checkPermission* method variants, passing in whatever permission or role representation is required.

Step 2: The Subject instance, typically a DelegatingSubject (or a subclass) delegates to the application’s SecurityManager by calling the securityManager’s nearly identical respective hasRole*, checkRole*, isPermitted*, or checkPermission* method variants (the securityManager implements the org.apache.shiro.authz.Authorizer interface, which defines all Subject-specific authorization methods).

Step 3: The SecurityManager, being a basic ‘umbrella’ component, relays/delegates to its internal org.apache.shiro.authz.Authorizer instance by calling the authorizer’s respective hasRole*, checkRole*, isPermitted*, or checkPermission* method. The authorizer instance is by default a ModularRealmAuthorizer instance, which supports coordinating one or more Realm instances during any authorization operation.

Step 4: Each configured Realm is checked to see if it implements the same Authorizer interface. If so, the Realm’s own respective hasRole*, checkRole*, isPermitted*, or checkPermission* method is called.

原始碼下載地址:

GITHUB原始碼下載地址:

本文章由[諳憶]編寫, 所有權利保留。
歡迎轉載,分享是進步的源泉。

相關推薦

ShiroShiro從小()-許可權認證(授權)

本節講許可權認證,也就是授權 基於角色的訪問控制和基於許可權的訪問控制的小例項 以及註解式授權和JSP標籤授權詳解 許可權認證 許可權認證核心要素 許可權認證,也就是訪問控制,即在應用中控制誰能訪問哪些資源 在許可權認證中,最核心的三

ShiroShiro從小(五)-自定義Realm

用資料庫的話,至少會涉及到這幾張表: 使用者表,角色表,許可權表 角色和使用者是一對多的關係 多個使用者可以擁有同一個角色 角色和許可權在這裡也是一對多的關係 一個角色可以擁有很多個許可權 資料庫表名: t_role 角色表 並插入如下資料

分類 - Shiro

專欄達人 授予成功建立個人部落格專欄

筆記shiro中的session設定:

1.匯入依賴包<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-guartz</artifactId><version>

ShiroShiro登入驗證失敗問題

shiro登入驗證一直失敗: 原因: 在使用者註冊時,採用如下加密方法: /** * md5加密工具 * @param var * 要加密的字串 * @param iterations * 加密次數 * @return */ public

筆記shiro中的RememberMe設定:

修改spring-shiro.xml檔案<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"><property name="name" value="m

shiroshiro學習筆記1-shiro初識

認證流程 環境 程式碼 總結 認證流程 Created with Raphaël 2.1.0Start構造SecurityManager環境Subject.login

Apache-Shiroshiro配置詳解

Apache-Shiro旨在簡化身份驗證和授權,為企業應用提供安全解決方案。 1.配置web.xml <filter> <filter-name>shiroFilter</filter-name>

洛谷P3376模板網絡最流  Dinic模板

span -c -s blog name sca print 技術 pop 之前的Dinic模板照著劉汝佳寫的vector然後十分鬼畜跑得奇慢無比,雖然別人這樣寫也沒慢多少但是自己的就是令人捉急。 改成鄰接表之後快了三倍,雖然還是比較慢但是自己比較滿意了。雖然一開始ecnt

hivehive表很的時候查詢報錯問題

一段時間 partition 查詢 query order exception concat 使用 小時   線上hive使用環境出現了一個奇怪的問題,跑一段時間就報如下錯誤: FAILED: SemanticException MetaException(message

洛谷P3376 模板網絡最

規模 ostream style 一次 ios 分層 nic i++ %d P3376 【模板】網絡最大流 題目描述 如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。 輸入輸出格式 輸入格式: 第一行包含四個正整數N

luogu3376 模板網絡最流 dinic

truct out ios div std main pty stream add 當前弧優化、單路增廣 #include <iostream> #include <cstring> #include <cstdio> #include

CF913FStrongly Connected Tournament 概率

左右 sca str names a* int tmp 一場 過程 【CF913F】Strongly Connected Tournament 題意:有n個人進行如下錦標賽: 1.所有人都和所有其他的人進行一場比賽,其中標號為i的人打贏標號為j的人(i<j)的概率

洛谷 P3376 模板網絡最

mem oid div pty ack turn color print from 題目描述 如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。 輸入 第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。 接下來M行每行包含三個

NOIP2013貨車運輸 最生成樹+倍增

nbsp get 最小值 每次 pac def tin map math 題目大意:給你一張n個點m條邊的圖,有q次詢問,每次讓你找出一條從x至y的路徑,使得路徑上經過的邊的最小值最大,輸出這個最大的最小值。 顯然,經過的路徑必然在這張圖的最大生成樹上。 我們求出這個圖

網路程式設計基礎day09:socket接收資料(五)

本節內容 1、概述 2、socket接收大資料 3、中文字元的坑 一、概述   上篇部落格寫到了,就是說當伺服器傳送至客戶端的資料,大於客戶端設定的資料,則就會把資料服務端發過來的資料剩餘資料存在IO緩衝區中,那我們如何解決這個問題呢?   有的同學就說了: 改大客戶端接收的資料的大小=&

分治輸出前k的數

描述 給定一個數組,統計前k大的數並且把這k個數從大到小輸出。 輸入第一行包含一個整數n,表示陣列的大小。n < 100000。第二行包含n個整數,表示陣列的元素,整數之間以一個空格分開。每個整數的絕對值不超過100000000。第三行包含一個整數k。k < n。輸出從大到小輸出前k大的數,每

筆記生成函式與揹包問題

網頁崩了。。。具體內容心情好了再貼。。。 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll p[100005]; 5 ll q[200005];

P3952 時間複雜度 模擬題解

  題目連結     完全模擬 1.模擬結果 當我們的模擬程式執行結束時,直接執行模擬結果函式,用於比對我們的結果和資料給出的結果。 1 bool yes(char a[],char b[]) 2 { 3 for(int i=0;

(轉)Spring事務異常回滾機制(出處在文末,轉自李慕

Spring事務異常回滾,捕獲異常不丟擲就不會回滾 推薦:Spring transaction 事務 --Isolation & Progation Java異常處理主要通過5個關鍵字控制:try、catch、throw、throws和finally。try的意思是試試它所包含的