Tuesday, June 12, 2012

Apache Wicket Auth/Roles 簡介 -- Authorization (3)

本文同樣延續上一篇的範例,本文會再新增兩個頁面,這些頁面會視使用者的角色而呈現出不同的內容。也可以說,頁面的內容可以自訂允許哪些角色看到什麼內容。

新增的兩個頁面分別是AdminPanelPage.html(使用meta data授權)及AdminAnnotationPanelPage.html(使用annotation授權)。

因此,在HomePage.html也要新增兩個超連結。



<div>
                <a href="#" wicket:id="adminBookmarkableLink">
                    前往bookmarkable AdminPage.html(使用metadata方式授權)
                </a>
                <br />
                <a href="#" wicket:id="adminInternalLink">
                    前往內部頁面AdminInternalPage.html(使用metadata方式授權)
                </a>
                <br />
                <a href="#" wicket:id="panelsPageLink">
                    前往Panel頁面AdminPanelPage.html(使用metadata方式授權)
                </a>
            </div>
            <br />
            <div>
                <a href="#" wicket:id="adminAnnotBookmarkableLink">
                    前往bookmarkable AdminAnnotationPage.html(使用annotation方式授權)
                </a>
                <br />
                <a href="#" wicket:id="adminAnnotInternalLink">
                    前往內部頁面AdminInternalAnnotationPage.html(使用annotation方式授權)
                </a>
                <br />
                <a href="#" wicket:id="panelsAnnotPageLink">
                    前往Panel頁面AdminAnnotationPanelPage.html(使用annotation方式授權)
                </a>
            </div>


在HomePage.java中要有相對應的程式碼。

//連到使用meta data授權方式的AdminPagelhtml
        add(new BookmarkablePageLink<Void>("adminBookmarkableLink", AdminPage.class));
        //連到使用meta data授權方式的AdminInternalPage.html
        add(new Link("adminInternalLink") {

            @Override
            public void onClick() {
                setResponsePage(new AdminInternalPage("foo"));
            }
        });
        //連到使用meta data授權方式的AdminPanelPage.html
        //此頁面含有3個panel,可以依授權角色而呈現不同的panel
        add(new BookmarkablePageLink<Void>("panelsPageLink", AdminPanelPage.class));

        //連到使用annotation授權方式的AdminAnnotationPagelhtml
        add(new BookmarkablePageLink<Void>("adminAnnotBookmarkableLink",
                AdminAnnotationPage.class));
        //連到使用annotation授權方式的AdminInternalAnnotationPagelhtml
        add(new Link("adminAnnotInternalLink") {

            @Override
            public void onClick() {
                setResponsePage(new AdminInternalAnnotationPage("bar"));
            }
        });
        //連到使用annotation授權方式的AdminAnnotationPanelPage.html
        //此頁面含有3個panel,可以依授權角色而呈現不同的panel
        add(new BookmarkablePageLink<Void>("panelsAnnotPageLink", AdminAnnotationPanelPage.class));


接下來我們要在AdminPanelPage.html中新增3個Panel(ForAllUsers.html、ForAdminsAndUsers.html及ForAdmins.html)。

首先要在AdminPanelPage.html中加入panel的markup。

<wicket:extend>
            這是PanelPage,依照角色的不同,可以看到的Panel也不同
            <br />
            本頁面以meta data進行授權

            <span wicket:id="forAllUsersPanel">
                所有人都可以看得到
            </span>

            <span wicket:id="forAdminsAndUsersPanel">
                ADMIN及USER可以看到
            </span>

            <span wicket:id="forAdminsPanel">
                只有ADMIN看的到
            </span>
        </wicket:extend>

相對應的AdminPanelPage.java。

package com.myapp.wicket;

import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;

public final class AdminPanelPage extends BasePage {

    public AdminPanelPage() {
        ForAllUsers forAllUsers = new ForAllUsers("forAllUsersPanel");
        add(forAllUsers);

        ForAdminsAndUsers forAdminsAndUsers = new ForAdminsAndUsers("forAdminsAndUsersPanel");
        add(forAdminsAndUsers);

        //使用meta data進行授權
        //允許進行Action.RENDER動作
        MetaDataRoleAuthorizationStrategy.authorize(forAdminsAndUsers, RENDER, "ADMIN");
        MetaDataRoleAuthorizationStrategy.authorize(forAdminsAndUsers, RENDER, "USER");

        ForAdmins forAdmins = new ForAdmins("forAdminsPanel");

        MetaDataRoleAuthorizationStrategy.authorize(forAdmins, RENDER, "ADMIN");
        add(forAdmins);
    }
}

接下來要建立三個自訂的Panel。


        <wicket:panel>
            <div style="border: solid; margin:2px; padding:2px;">
                此Panel只有ADMIN才看的到
            </div>
        </wicket:panel>

        <wicket:panel>
            <div style="border: solid; margin:2px; padding:2px;">
                此Panel只有ADMIN及USER才看的到
            </div>
        </wicket:panel>

        <wicket:panel>
            <div style="border: solid; margin:2px; padding:2px;">
                此Panel所有人都看得到
            </div>
        </wicket:panel>

和三個Panel相對應的java原始碼。

//forAdmins.java

package com.myapp.wicket;

import org.apache.wicket.markup.html.panel.Panel;

public final class ForAdmins extends Panel {

    public ForAdmins(String id) {
        super(id);
    }
}

//forAdminsAndUsers.java

package com.myapp.wicket;

import org.apache.wicket.markup.html.panel.Panel;

public final class ForAdminsAndUsers extends Panel {

    public ForAdminsAndUsers(String id) {
        super(id);
    }
}

//forAllUsers.java

package com.myapp.wicket;

import org.apache.wicket.markup.html.panel.Panel;

public final class ForAllUsers extends Panel {

    public ForAllUsers(String id) {
        super(id);
    }
}




再接下來,我們來建立使用annotation授權的AdminAnnotationPanelPage.html及4個相關panel(AnnoForAdmins.html、AnnoForAdminsAndUsers.html及AnnoForAllUsers.html及AnnoTest.html)。AnnoTest.html則是一個可以點選後隱藏/顯現的panel。


        <wicket:extend>
            這是PanelPage,依照角色的不同,可以看到的Panel也不同
            <br />
            本頁面以annotation進行授權
            <span wicket:id="forAllUsersPanel">
                所有人都可以看得到
            </span>

            <span wicket:id="forAdminsAndUsersPanel">
                ADMIN及USER可以看得到
            </span>

            <span wicket:id="forAdminsPanel">
                ADMIN看得到
            </span>
            <!--這裡使用WebMarkupContainer來容納相關的元件-->
            <a href="#" wicket:id="link">切換開關</a>
            <div wicket:id="outer">
                <span wicket:id="test">[沒有東西在這裡]</span>
            </div>
        </wicket:extend>


        <wicket:panel>
            <div style="border: solid; margin:2px; padding:2px;">
                此Panel只有ADMIN才看的到
            </div>
        </wicket:panel>


        <wicket:panel>
            <div style="border: solid; margin:2px; padding:2px;">
                此Panel只有ADMIN及USER才看的到
            </div>
        </wicket:panel>


        <wicket:panel>
            <div style="border: solid; margin:2px; padding:2px;">
                此Panel所有人都看得到
            </div>
        </wicket:panel>


        <wicket:panel>
            <div style="border: solid; margin:2px; padding:2px;">
                這個Panel只有在角色ADMIN及USER才看得到
            </div>
            <ul>
                <li wicket:id="list">
                    <!--以下會因為不使角色(USER,ADMIN)而有不同的內容-->
                    <span wicket:id="userLabel">[USER:標籤列表]</span>
                    <span wicket:id="adminLabel">[ADMIN:標籤列表]</span>
                </li>
            </ul>
        </wicket:panel>



以下則是各個使用annotation授權的panel相對應的java原始碼。

//AdminAnnotationPanelPage.java
package com.myapp.wicket;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;

public final class AdminAnnotationPanelPage extends BasePage {

    //使用內容的容器來容納AnnoTest這個panel
    private WebMarkupContainer outer;
    //用來切換outer是否顯示的開關
    private boolean showDummy = true;

    public AdminAnnotationPanelPage() {
        //加入所有人都可以看到的panel
        add(new AnnoForAllUsers("forAllUsersPanel"));
        //只有ADMIN及USER才可以看得到
        add(new AnnoForAdminsAndUsers("forAdminsAndUsersPanel"));
        //只有ADMIN才可以看得到
        add(new AnnoForAdmins("forAdminsPanel"));
        //可以讓使用者自由切換是否顯示
        add(outer = new WebMarkupContainer("outer"));
        //為了要讓Ajax可以在背景request,並即時顯示
        //所以要取得markupid
        outer.setOutputMarkupId(true);
        //在outer中再加入另一個容器
        //這個容器會再加入另一個容器
        outer.add(new WebMarkupContainer("test").setOutputMarkupId(true));
        add(new AjaxLink<Void>("link") {

            @Override
            public void onClick(AjaxRequestTarget target) {
                showDummy = !showDummy;
                if (showDummy) {
                    //使用replace來替換容器的內容
                    //需注意child id必須相同(在此為test)
                    outer.replace(new WebMarkupContainer("test"));
                } else {
                    outer.replace(new AnnoTest("test"));
                }
                target.add(outer);
            }
        });
    }
}


//AnnoForAdmins.java
package com.myapp.wicket;

import org.apache.wicket.authorization.Action;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeAction;
import org.apache.wicket.markup.html.panel.Panel;

//僅授權ADMIN可以顯示(RENDER)
@AuthorizeAction(action = Action.RENDER, roles = Roles.ADMIN)
public final class AnnoForAdmins extends Panel {

    public AnnoForAdmins(String id) {
        super(id);
    }
}

//AnnoForAdminsAndUsers.java
package com.myapp.wicket;

import org.apache.wicket.authorization.Action;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeAction;
import org.apache.wicket.markup.html.panel.Panel;

//僅容許ADMIN及USER
@AuthorizeAction(action = Action.RENDER, roles = { Roles.ADMIN, Roles.USER })
public final class AnnoForAdminsAndUsers extends Panel {

    public AnnoForAdminsAndUsers(String id) {
        super(id);
    }
}

//AnnoForAllUsers.java
package com.myapp.wicket;

import org.apache.wicket.markup.html.panel.Panel;

//不做annotation標示
//所有人都可以看得到
public final class AnnoForAllUsers extends Panel {

    public AnnoForAllUsers(String id) {
        super(id);
    }
}

//AnnoTest.java
package com.myapp.wicket;

import java.util.Arrays;
import java.util.List;
import org.apache.wicket.authorization.Action;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeAction;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;

//授權ADMIN及USER
@AuthorizeAction(action = Action.RENDER, roles = {Roles.ADMIN, Roles.USER})
public final class AnnoTest extends Panel {

    public AnnoTest(String id) {
        super(id);
        List<String> l = Arrays.asList("1", "2", "3", "4", "5");
        ListView<String> listView = new ListView<String>("list", l) {

            @Override
            protected void populateItem(ListItem<String> item) {
                String i = item.getDefaultModelObjectAsString();
                item.add(new UserLabel("userLabel", i));
                item.add(new AdminLabel("adminLabel", i));
            }
        };
        add(listView);
        listView.setReuseItems(true);
    }

    //USER標籤
    //授權USER可顯示(意思是ADMIN看不到)
    @AuthorizeAction(action = Action.RENDER, roles = Roles.USER)
    private static class UserLabel extends Label {

        public UserLabel(String id, String nbr) {
            super(id, "USER標籤: " + nbr);
        }
    }

    //ADMIN標籤
    //授權ADMIN可顯示
    @AuthorizeAction(action = Action.RENDER, roles = Roles.ADMIN)
    private static class AdminLabel extends Label {

        public AdminLabel(String id, String nbr) {
            super(id, "ADMIN標籤: " + nbr);
        }
    }
}


至此,大功告成!

No comments:

Post a Comment