diff --git a/src/main/java/org/codelibs/fess/Constants.java b/src/main/java/org/codelibs/fess/Constants.java
index 99c6090085e075cb9f805bfd7795eeacb56f3638..ad8240195f5291df7aede24d2b0f7034ca809d4f 100644
--- a/src/main/java/org/codelibs/fess/Constants.java
+++ b/src/main/java/org/codelibs/fess/Constants.java
@@ -358,8 +358,6 @@ public class Constants extends CoreLibConstants {
 
     public static final String ES_API_ACCESS_TOKEN = "esApiAccessToken";
 
-    public static final String ADMIN_PACKAGE = "org.codelibs.fess.app.web.admin";
-
     public static final String DEFAULT_FIELD = "_default";
 
     public static final Integer DEFAULT_DAY_FOR_CLEANUP = 3;
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/AdminAction.java b/src/main/java/org/codelibs/fess/app/web/admin/AdminAction.java
index 8d440a8a192c041e9e88278a965129ec4e7a7d22..4b6b7f24eed89c56920f471546696dcf0f6fd52b 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/AdminAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/AdminAction.java
@@ -15,8 +15,46 @@
  */
 package org.codelibs.fess.app.web.admin;
 
+import org.codelibs.fess.app.web.admin.accesstoken.AdminAccesstokenAction;
+import org.codelibs.fess.app.web.admin.backup.AdminBackupAction;
+import org.codelibs.fess.app.web.admin.badword.AdminBadwordAction;
+import org.codelibs.fess.app.web.admin.boostdoc.AdminBoostdocAction;
+import org.codelibs.fess.app.web.admin.crawlinginfo.AdminCrawlinginfoAction;
 import org.codelibs.fess.app.web.admin.dashboard.AdminDashboardAction;
+import org.codelibs.fess.app.web.admin.dataconfig.AdminDataconfigAction;
+import org.codelibs.fess.app.web.admin.design.AdminDesignAction;
+import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
+import org.codelibs.fess.app.web.admin.duplicatehost.AdminDuplicatehostAction;
+import org.codelibs.fess.app.web.admin.elevateword.AdminElevatewordAction;
+import org.codelibs.fess.app.web.admin.esreq.AdminEsreqAction;
+import org.codelibs.fess.app.web.admin.failureurl.AdminFailureurlAction;
+import org.codelibs.fess.app.web.admin.fileauth.AdminFileauthAction;
+import org.codelibs.fess.app.web.admin.fileconfig.AdminFileconfigAction;
+import org.codelibs.fess.app.web.admin.general.AdminGeneralAction;
+import org.codelibs.fess.app.web.admin.group.AdminGroupAction;
+import org.codelibs.fess.app.web.admin.joblog.AdminJoblogAction;
+import org.codelibs.fess.app.web.admin.keymatch.AdminKeymatchAction;
+import org.codelibs.fess.app.web.admin.labeltype.AdminLabeltypeAction;
+import org.codelibs.fess.app.web.admin.log.AdminLogAction;
+import org.codelibs.fess.app.web.admin.maintenance.AdminMaintenanceAction;
+import org.codelibs.fess.app.web.admin.pathmap.AdminPathmapAction;
+import org.codelibs.fess.app.web.admin.plugin.AdminPluginAction;
+import org.codelibs.fess.app.web.admin.relatedcontent.AdminRelatedcontentAction;
+import org.codelibs.fess.app.web.admin.relatedquery.AdminRelatedqueryAction;
+import org.codelibs.fess.app.web.admin.reqheader.AdminReqheaderAction;
+import org.codelibs.fess.app.web.admin.role.AdminRoleAction;
+import org.codelibs.fess.app.web.admin.scheduler.AdminSchedulerAction;
+import org.codelibs.fess.app.web.admin.searchlog.AdminSearchlogAction;
+import org.codelibs.fess.app.web.admin.storage.AdminStorageAction;
+import org.codelibs.fess.app.web.admin.suggest.AdminSuggestAction;
+import org.codelibs.fess.app.web.admin.systeminfo.AdminSysteminfoAction;
+import org.codelibs.fess.app.web.admin.user.AdminUserAction;
+import org.codelibs.fess.app.web.admin.webauth.AdminWebauthAction;
+import org.codelibs.fess.app.web.admin.webconfig.AdminWebconfigAction;
+import org.codelibs.fess.app.web.admin.wizard.AdminWizardAction;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
+import org.codelibs.fess.mylasta.action.FessUserBean;
 import org.lastaflute.web.Execute;
 import org.lastaflute.web.response.HtmlResponse;
 
@@ -34,8 +72,322 @@ public class AdminAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ //
+    AdminDashboardAction.ROLE, //
+            AdminDashboardAction.ROLE + VIEW, //
+            AdminWizardAction.ROLE, //
+            AdminWizardAction.ROLE + VIEW, //
+            AdminGeneralAction.ROLE, //
+            AdminGeneralAction.ROLE + VIEW, //
+            AdminSchedulerAction.ROLE, //
+            AdminSchedulerAction.ROLE + VIEW, //
+            AdminDesignAction.ROLE, //
+            AdminDesignAction.ROLE + VIEW, //
+            AdminDictAction.ROLE, //
+            AdminDictAction.ROLE + VIEW, //
+            AdminAccesstokenAction.ROLE, //
+            AdminAccesstokenAction.ROLE + VIEW, //
+            AdminPluginAction.ROLE, //
+            AdminPluginAction.ROLE + VIEW, //
+            AdminStorageAction.ROLE, //
+            AdminStorageAction.ROLE + VIEW, //
+            AdminWebconfigAction.ROLE, //
+            AdminWebconfigAction.ROLE + VIEW, //
+            AdminFileconfigAction.ROLE, //
+            AdminFileconfigAction.ROLE + VIEW, //
+            AdminDataconfigAction.ROLE, //
+            AdminDataconfigAction.ROLE + VIEW, //
+            AdminLabeltypeAction.ROLE, //
+            AdminLabeltypeAction.ROLE + VIEW, //
+            AdminKeymatchAction.ROLE, //
+            AdminKeymatchAction.ROLE + VIEW, //
+            AdminBoostdocAction.ROLE, //
+            AdminBoostdocAction.ROLE + VIEW, //
+            AdminRelatedcontentAction.ROLE, //
+            AdminRelatedcontentAction.ROLE + VIEW, //
+            AdminRelatedqueryAction.ROLE, //
+            AdminRelatedqueryAction.ROLE + VIEW, //
+            AdminPathmapAction.ROLE, //
+            AdminPathmapAction.ROLE + VIEW, //
+            AdminWebauthAction.ROLE, //
+            AdminWebauthAction.ROLE + VIEW, //
+            AdminFileauthAction.ROLE, //
+            AdminFileauthAction.ROLE + VIEW, //
+            AdminReqheaderAction.ROLE, //
+            AdminReqheaderAction.ROLE + VIEW, //
+            AdminDuplicatehostAction.ROLE, //
+            AdminDuplicatehostAction.ROLE + VIEW, //
+            AdminUserAction.ROLE, //
+            AdminUserAction.ROLE + VIEW, //
+            AdminRoleAction.ROLE, //
+            AdminRoleAction.ROLE + VIEW, //
+            AdminGroupAction.ROLE, //
+            AdminGroupAction.ROLE + VIEW, //
+            AdminSuggestAction.ROLE, //
+            AdminSuggestAction.ROLE + VIEW, //
+            AdminElevatewordAction.ROLE, //
+            AdminElevatewordAction.ROLE + VIEW, //
+            AdminBadwordAction.ROLE, //
+            AdminBadwordAction.ROLE + VIEW, //
+            AdminSysteminfoAction.ROLE, //
+            AdminSysteminfoAction.ROLE + VIEW, //
+            AdminSearchlogAction.ROLE, //
+            AdminSearchlogAction.ROLE + VIEW, //
+            AdminJoblogAction.ROLE, //
+            AdminJoblogAction.ROLE + VIEW, //
+            AdminCrawlinginfoAction.ROLE, //
+            AdminCrawlinginfoAction.ROLE + VIEW, //
+            AdminLogAction.ROLE, //
+            AdminLogAction.ROLE + VIEW, //
+            AdminFailureurlAction.ROLE, //
+            AdminFailureurlAction.ROLE + VIEW, //
+            AdminBackupAction.ROLE, //
+            AdminBackupAction.ROLE + VIEW, //
+            AdminMaintenanceAction.ROLE, //
+            AdminMaintenanceAction.ROLE + VIEW, //
+            AdminEsreqAction.ROLE, //
+            AdminEsreqAction.ROLE + VIEW, //
+            AdminDashboardAction.ROLE, //
+            AdminDashboardAction.ROLE + VIEW, //
+            AdminWizardAction.ROLE, //
+            AdminWizardAction.ROLE + VIEW, //
+            AdminGeneralAction.ROLE, //
+            AdminGeneralAction.ROLE + VIEW, //
+            AdminSchedulerAction.ROLE, //
+            AdminSchedulerAction.ROLE + VIEW, //
+            AdminDesignAction.ROLE, //
+            AdminDesignAction.ROLE + VIEW, //
+            AdminDictAction.ROLE, //
+            AdminDictAction.ROLE + VIEW, //
+            AdminAccesstokenAction.ROLE, //
+            AdminAccesstokenAction.ROLE + VIEW, //
+            AdminPluginAction.ROLE, //
+            AdminPluginAction.ROLE + VIEW, //
+            AdminStorageAction.ROLE, //
+            AdminStorageAction.ROLE + VIEW, //
+            AdminWebconfigAction.ROLE, //
+            AdminWebconfigAction.ROLE + VIEW, //
+            AdminFileconfigAction.ROLE, //
+            AdminFileconfigAction.ROLE + VIEW, //
+            AdminDataconfigAction.ROLE, //
+            AdminDataconfigAction.ROLE + VIEW, //
+            AdminLabeltypeAction.ROLE, //
+            AdminLabeltypeAction.ROLE + VIEW, //
+            AdminKeymatchAction.ROLE, //
+            AdminKeymatchAction.ROLE + VIEW, //
+            AdminBoostdocAction.ROLE, //
+            AdminBoostdocAction.ROLE + VIEW, //
+            AdminRelatedcontentAction.ROLE, //
+            AdminRelatedcontentAction.ROLE + VIEW, //
+            AdminRelatedqueryAction.ROLE, //
+            AdminRelatedqueryAction.ROLE + VIEW, //
+            AdminPathmapAction.ROLE, //
+            AdminPathmapAction.ROLE + VIEW, //
+            AdminWebauthAction.ROLE, //
+            AdminWebauthAction.ROLE + VIEW, //
+            AdminFileauthAction.ROLE, //
+            AdminFileauthAction.ROLE + VIEW, //
+            AdminReqheaderAction.ROLE, //
+            AdminReqheaderAction.ROLE + VIEW, //
+            AdminDuplicatehostAction.ROLE, //
+            AdminDuplicatehostAction.ROLE + VIEW, //
+            AdminUserAction.ROLE, //
+            AdminUserAction.ROLE + VIEW, //
+            AdminRoleAction.ROLE, //
+            AdminRoleAction.ROLE + VIEW, //
+            AdminGroupAction.ROLE, //
+            AdminGroupAction.ROLE + VIEW, //
+            AdminSuggestAction.ROLE, //
+            AdminSuggestAction.ROLE + VIEW, //
+            AdminElevatewordAction.ROLE, //
+            AdminElevatewordAction.ROLE + VIEW, //
+            AdminBadwordAction.ROLE, //
+            AdminBadwordAction.ROLE + VIEW, //
+            AdminSysteminfoAction.ROLE, //
+            AdminSysteminfoAction.ROLE + VIEW, //
+            AdminSearchlogAction.ROLE, //
+            AdminSearchlogAction.ROLE + VIEW, //
+            AdminJoblogAction.ROLE, //
+            AdminJoblogAction.ROLE + VIEW, //
+            AdminCrawlinginfoAction.ROLE, //
+            AdminCrawlinginfoAction.ROLE + VIEW, //
+            AdminLogAction.ROLE, //
+            AdminLogAction.ROLE + VIEW, //
+            AdminFailureurlAction.ROLE, //
+            AdminFailureurlAction.ROLE + VIEW, //
+            AdminBackupAction.ROLE, //
+            AdminBackupAction.ROLE + VIEW, //
+            AdminMaintenanceAction.ROLE, //
+            AdminMaintenanceAction.ROLE + VIEW, //
+            AdminEsreqAction.ROLE, //
+            AdminEsreqAction.ROLE + VIEW, //
+            AdminDashboardAction.ROLE, //
+            AdminDashboardAction.ROLE + VIEW, //
+            AdminWizardAction.ROLE, //
+            AdminWizardAction.ROLE + VIEW, //
+            AdminGeneralAction.ROLE, //
+            AdminGeneralAction.ROLE + VIEW, //
+            AdminSchedulerAction.ROLE, //
+            AdminSchedulerAction.ROLE + VIEW, //
+            AdminDesignAction.ROLE, //
+            AdminDesignAction.ROLE + VIEW, //
+            AdminDictAction.ROLE, //
+            AdminDictAction.ROLE + VIEW, //
+            AdminAccesstokenAction.ROLE, //
+            AdminAccesstokenAction.ROLE + VIEW, //
+            AdminPluginAction.ROLE, //
+            AdminPluginAction.ROLE + VIEW, //
+            AdminStorageAction.ROLE, //
+            AdminStorageAction.ROLE + VIEW, //
+            AdminWebconfigAction.ROLE, //
+            AdminWebconfigAction.ROLE + VIEW, //
+            AdminFileconfigAction.ROLE, //
+            AdminFileconfigAction.ROLE + VIEW, //
+            AdminDataconfigAction.ROLE, //
+            AdminDataconfigAction.ROLE + VIEW, //
+            AdminLabeltypeAction.ROLE, //
+            AdminLabeltypeAction.ROLE + VIEW, //
+            AdminKeymatchAction.ROLE, //
+            AdminKeymatchAction.ROLE + VIEW, //
+            AdminBoostdocAction.ROLE, //
+            AdminBoostdocAction.ROLE + VIEW, //
+            AdminRelatedcontentAction.ROLE, //
+            AdminRelatedcontentAction.ROLE + VIEW, //
+            AdminRelatedqueryAction.ROLE, //
+            AdminRelatedqueryAction.ROLE + VIEW, //
+            AdminPathmapAction.ROLE, //
+            AdminPathmapAction.ROLE + VIEW, //
+            AdminWebauthAction.ROLE, //
+            AdminWebauthAction.ROLE + VIEW, //
+            AdminFileauthAction.ROLE, //
+            AdminFileauthAction.ROLE + VIEW, //
+            AdminReqheaderAction.ROLE, //
+            AdminReqheaderAction.ROLE + VIEW, //
+            AdminDuplicatehostAction.ROLE, //
+            AdminDuplicatehostAction.ROLE + VIEW, //
+            AdminUserAction.ROLE, //
+            AdminUserAction.ROLE + VIEW, //
+            AdminRoleAction.ROLE, //
+            AdminRoleAction.ROLE + VIEW, //
+            AdminGroupAction.ROLE, //
+            AdminGroupAction.ROLE + VIEW, //
+            AdminSuggestAction.ROLE, //
+            AdminSuggestAction.ROLE + VIEW, //
+            AdminElevatewordAction.ROLE, //
+            AdminElevatewordAction.ROLE + VIEW, //
+            AdminBadwordAction.ROLE, //
+            AdminBadwordAction.ROLE + VIEW, //
+            AdminSysteminfoAction.ROLE, //
+            AdminSysteminfoAction.ROLE + VIEW, //
+            AdminSearchlogAction.ROLE, //
+            AdminSearchlogAction.ROLE + VIEW, //
+            AdminJoblogAction.ROLE, //
+            AdminJoblogAction.ROLE + VIEW, //
+            AdminCrawlinginfoAction.ROLE, //
+            AdminCrawlinginfoAction.ROLE + VIEW, //
+            AdminLogAction.ROLE, //
+            AdminLogAction.ROLE + VIEW, //
+            AdminFailureurlAction.ROLE, //
+            AdminFailureurlAction.ROLE + VIEW, //
+            AdminBackupAction.ROLE, //
+            AdminBackupAction.ROLE + VIEW, //
+            AdminMaintenanceAction.ROLE, //
+            AdminMaintenanceAction.ROLE + VIEW, //
+            AdminEsreqAction.ROLE, //
+            AdminEsreqAction.ROLE + VIEW,//
+
+    })
     public HtmlResponse index() {
-        return redirect(AdminDashboardAction.class);
+        return redirect(getUserBean().map(user -> {
+            Class<? extends FessAdminAction> actionClass = getAdminActionClass(user);
+            if (actionClass != null) {
+                return actionClass;
+            }
+            return AdminDashboardAction.class;
+        }).orElse(AdminDashboardAction.class));
+    }
+
+    public static Class<? extends FessAdminAction> getAdminActionClass(FessUserBean user) {
+        if (user.hasRoles(getActionRoles(AdminDashboardAction.ROLE))) {
+            return AdminDashboardAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminWizardAction.ROLE))) {
+            return AdminWizardAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminGeneralAction.ROLE))) {
+            return AdminGeneralAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminSchedulerAction.ROLE))) {
+            return AdminSchedulerAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminDesignAction.ROLE))) {
+            return AdminDesignAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminDictAction.ROLE))) {
+            return AdminDictAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminAccesstokenAction.ROLE))) {
+            return AdminAccesstokenAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminPluginAction.ROLE))) {
+            return AdminPluginAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminStorageAction.ROLE))) {
+            return AdminStorageAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminWebconfigAction.ROLE))) {
+            return AdminWebconfigAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminFileconfigAction.ROLE))) {
+            return AdminFileconfigAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminDataconfigAction.ROLE))) {
+            return AdminDataconfigAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminLabeltypeAction.ROLE))) {
+            return AdminLabeltypeAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminKeymatchAction.ROLE))) {
+            return AdminKeymatchAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminBoostdocAction.ROLE))) {
+            return AdminBoostdocAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminRelatedcontentAction.ROLE))) {
+            return AdminRelatedcontentAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminRelatedqueryAction.ROLE))) {
+            return AdminRelatedqueryAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminPathmapAction.ROLE))) {
+            return AdminPathmapAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminWebauthAction.ROLE))) {
+            return AdminWebauthAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminFileauthAction.ROLE))) {
+            return AdminFileauthAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminReqheaderAction.ROLE))) {
+            return AdminReqheaderAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminDuplicatehostAction.ROLE))) {
+            return AdminDuplicatehostAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminUserAction.ROLE))) {
+            return AdminUserAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminRoleAction.ROLE))) {
+            return AdminRoleAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminGroupAction.ROLE))) {
+            return AdminGroupAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminSuggestAction.ROLE))) {
+            return AdminSuggestAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminElevatewordAction.ROLE))) {
+            return AdminElevatewordAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminBadwordAction.ROLE))) {
+            return AdminBadwordAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminSysteminfoAction.ROLE))) {
+            return AdminSysteminfoAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminSearchlogAction.ROLE))) {
+            return AdminSearchlogAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminJoblogAction.ROLE))) {
+            return AdminJoblogAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminCrawlinginfoAction.ROLE))) {
+            return AdminCrawlinginfoAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminLogAction.ROLE))) {
+            return AdminLogAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminFailureurlAction.ROLE))) {
+            return AdminFailureurlAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminBackupAction.ROLE))) {
+            return AdminBackupAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminMaintenanceAction.ROLE))) {
+            return AdminMaintenanceAction.class;
+        } else if (user.hasRoles(getActionRoles(AdminEsreqAction.ROLE))) {
+            return AdminEsreqAction.class;
+        }
+        return null;
+    }
+
+    private static String[] getActionRoles(final String role) {
+        return new String[] { role, role + VIEW };
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/accesstoken/AdminAccesstokenAction.java b/src/main/java/org/codelibs/fess/app/web/admin/accesstoken/AdminAccesstokenAction.java
index a486d358c17875f56fde7539a69046c9c432aa56..8b9199d85d54156a1d19337087104aabc232b697 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/accesstoken/AdminAccesstokenAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/accesstoken/AdminAccesstokenAction.java
@@ -28,6 +28,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.AccessTokenPager;
 import org.codelibs.fess.app.service.AccessTokenService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.AccessToken;
 import org.codelibs.fess.helper.PermissionHelper;
@@ -46,6 +47,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminAccesstokenAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-accesstoken";
+
     public static final String TOKEN = "token";
 
     public static final String EXPIRES = "expires";
@@ -73,11 +76,13 @@ public class AdminAccesstokenAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             accessTokenPager.setCurrentPageNumber(pageNumber.get());
@@ -90,6 +95,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, accessTokenPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminAccesstoken_AdminAccesstokenJsp).renderWith(data -> {
@@ -98,6 +104,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         accessTokenPager.clear();
         return asHtml(path_AdminAccesstoken_AdminAccesstokenJsp).renderWith(data -> {
@@ -119,6 +126,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asEditHtml().useForm(CreateForm.class, op -> {
@@ -133,6 +141,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -162,6 +171,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -197,6 +207,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -218,6 +229,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -238,6 +250,7 @@ public class AdminAccesstokenAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java b/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java
index 5971697aa06f672a417da63ba24172e650b71c4e..0d6d4a8528aba6a16ce0f05fd3d7163f135e6cf3 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java
@@ -53,6 +53,7 @@ import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.Pair;
 import org.codelibs.curl.CurlResponse;
 import org.codelibs.fess.Constants;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exbhv.FileConfigBhv;
 import org.codelibs.fess.es.config.exbhv.LabelTypeBhv;
@@ -82,6 +83,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
  */
 public class AdminBackupAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-backup";
+
     private static final Logger logger = LogManager.getLogger(AdminBackupAction.class);
 
     public static final String NDJSON_EXTENTION = ".ndjson";
@@ -107,12 +110,14 @@ public class AdminBackupAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         verifyToken(() -> asListHtml());
@@ -285,6 +290,7 @@ public class AdminBackupAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final String id) {
         if (stream(fessConfig.getIndexBackupAllTargets()).get(stream -> stream.anyMatch(s -> s.equals(id)))) {
             if (id.equals("system.properties")) {
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/badword/AdminBadwordAction.java b/src/main/java/org/codelibs/fess/app/web/admin/badword/AdminBadwordAction.java
index 5a6e73bfa5dd726176c136431a8a355035771aeb..dab86e7142eb403b2bc5750d3b08898789085895 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/badword/AdminBadwordAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/badword/AdminBadwordAction.java
@@ -33,6 +33,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.BadWordPager;
 import org.codelibs.fess.app.service.BadWordService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.BadWord;
 import org.codelibs.fess.exception.FessSystemException;
@@ -53,6 +54,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminBadwordAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-badword";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -76,11 +79,13 @@ public class AdminBadwordAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             badWordPager.setCurrentPageNumber(pageNumber.get());
@@ -93,6 +98,7 @@ public class AdminBadwordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, badWordPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
@@ -101,6 +107,7 @@ public class AdminBadwordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         badWordPager.clear();
         return asHtml(path_AdminBadword_AdminBadwordJsp).renderWith(data -> {
@@ -122,6 +129,7 @@ public class AdminBadwordAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asEditHtml().useForm(CreateForm.class, op -> {
@@ -133,6 +141,7 @@ public class AdminBadwordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -156,6 +165,7 @@ public class AdminBadwordAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -177,12 +187,14 @@ public class AdminBadwordAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse downloadpage() {
         saveToken();
         return asDownloadHtml();
     }
 
     @Execute
+    @Secured({ ROLE })
     public ActionResponse download(final DownloadForm form) {
         verifyToken(() -> asDownloadHtml());
 
@@ -207,6 +219,7 @@ public class AdminBadwordAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage() {
         saveToken();
         return asUploadHtml();
@@ -216,6 +229,7 @@ public class AdminBadwordAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -237,6 +251,7 @@ public class AdminBadwordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -258,6 +273,7 @@ public class AdminBadwordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
@@ -283,6 +299,7 @@ public class AdminBadwordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> asUploadHtml());
         verifyToken(() -> asUploadHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/boostdoc/AdminBoostdocAction.java b/src/main/java/org/codelibs/fess/app/web/admin/boostdoc/AdminBoostdocAction.java
index bdb3a27844c654db0998bae2fd3f726d679b5bdb..9d030f1f86d8bd6bba35f0afdbb07df47be66a26 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/boostdoc/AdminBoostdocAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/boostdoc/AdminBoostdocAction.java
@@ -22,6 +22,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.BoostDocPager;
 import org.codelibs.fess.app.service.BoostDocumentRuleService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.BoostDocumentRule;
 import org.codelibs.fess.helper.SystemHelper;
@@ -39,6 +40,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminBoostdocAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-boostdoc";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -60,11 +63,13 @@ public class AdminBoostdocAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             boostDocPager.setCurrentPageNumber(pageNumber.get());
@@ -77,6 +82,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, boostDocPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminBoostdoc_AdminBoostdocJsp).renderWith(data -> {
@@ -85,6 +91,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         boostDocPager.clear();
         return asHtml(path_AdminBoostdoc_AdminBoostdocJsp).renderWith(data -> {
@@ -106,6 +113,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asEditHtml().useForm(CreateForm.class, op -> {
@@ -117,6 +125,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -140,6 +149,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -161,6 +171,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -181,6 +192,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -201,6 +213,7 @@ public class AdminBoostdocAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java b/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java
index 800090dc71a71f57c585174288626de6d199f1d8..5d2dbc180d94b543abcc65b5463fa1a3c45cbb4c 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java
@@ -23,6 +23,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.CrawlingInfoPager;
 import org.codelibs.fess.app.service.CrawlingInfoService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.helper.ProcessHelper;
 import org.codelibs.fess.util.RenderDataUtil;
@@ -37,6 +38,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminCrawlinginfoAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-crawlinginfo";
+
     private static final Logger logger = LogManager.getLogger(AdminCrawlinginfoAction.class);
 
     // ===================================================================================
@@ -62,12 +65,14 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final Integer pageNumber, final SearchForm form) {
         saveToken();
         crawlingInfoPager.setCurrentPageNumber(pageNumber);
@@ -77,6 +82,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         saveToken();
         copyBeanToBean(form, crawlingInfoPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -86,6 +92,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         saveToken();
         crawlingInfoPager.clear();
@@ -95,6 +102,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse back(final SearchForm form) {
         saveToken();
         return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoJsp).renderWith(data -> {
@@ -117,6 +125,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -139,6 +148,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse threaddump(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
@@ -162,6 +172,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
@@ -175,6 +186,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse deleteall() {
         verifyToken(() -> asListHtml());
         crawlingInfoService.deleteOldSessions(processHelper.getRunningSessionIdSet());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dashboard/AdminDashboardAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dashboard/AdminDashboardAction.java
index 79e53678251347d83a54935d56dc00aa4b3604d4..c3daad82073ae633e68ebf7ba254ccd55aa10d68 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dashboard/AdminDashboardAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dashboard/AdminDashboardAction.java
@@ -18,6 +18,7 @@ package org.codelibs.fess.app.web.admin.dashboard;
 import javax.annotation.Resource;
 
 import org.codelibs.fess.api.es.EsApiManager;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.util.RenderDataUtil;
 import org.lastaflute.web.Execute;
@@ -30,6 +31,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminDashboardAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dashboard";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -50,6 +53,7 @@ public class AdminDashboardAction extends FessAdminAction {
     //                                                                              Index
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse index() {
         esApiManager.saveToken();
         return asHtml(path_AdminDashboard_AdminDashboardJsp).renderWith(data -> {
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dataconfig/AdminDataconfigAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dataconfig/AdminDataconfigAction.java
index 499031438e680f123f7add913f4ecf865dadd091..ea5269f79304040d842adc0dac2af01f5a78914b 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dataconfig/AdminDataconfigAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dataconfig/AdminDataconfigAction.java
@@ -33,6 +33,7 @@ import org.codelibs.fess.app.pager.DataConfigPager;
 import org.codelibs.fess.app.service.DataConfigService;
 import org.codelibs.fess.app.service.RoleTypeService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.ds.DataStoreFactory;
 import org.codelibs.fess.es.config.exentity.DataConfig;
@@ -53,6 +54,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminDataconfigAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dataconfig";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -78,11 +81,13 @@ public class AdminDataconfigAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             dataConfigPager.setCurrentPageNumber(pageNumber.get());
@@ -95,6 +100,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, dataConfigPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminDataconfig_AdminDataconfigJsp).renderWith(data -> {
@@ -103,6 +109,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         dataConfigPager.clear();
         return asHtml(path_AdminDataconfig_AdminDataconfigJsp).renderWith(data -> {
@@ -125,6 +132,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asEditHtml().useForm(CreateForm.class, op -> {
@@ -136,6 +144,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -174,6 +183,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -211,6 +221,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -231,6 +242,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -251,6 +263,7 @@ public class AdminDataconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/design/AdminDesignAction.java b/src/main/java/org/codelibs/fess/app/web/admin/design/AdminDesignAction.java
index b18bf9db37e2111e17a27ccb548d529c400bc4e4..a20f1cdf328a84c8fa9a89f145b83af75a89577e 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/design/AdminDesignAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/design/AdminDesignAction.java
@@ -31,6 +31,7 @@ import org.codelibs.core.io.ResourceUtil;
 import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.Pair;
 import org.codelibs.fess.Constants;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.exception.FessSystemException;
 import org.codelibs.fess.util.ComponentUtil;
@@ -47,6 +48,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminDesignAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-design";
+
     private static final Logger logger = LogManager.getLogger(AdminDesignAction.class);
 
     // ===================================================================================
@@ -112,18 +115,21 @@ public class AdminDesignAction extends FessAdminAction {
     //                                                                             Execute
     //                                                                             =======
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asHtml(path_AdminDesign_AdminDesignJsp).useForm(DesignForm.class);
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse back() {
         saveToken();
         return asHtml(path_AdminDesign_AdminDesignJsp).useForm(DesignForm.class);
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> asListHtml(form));
         verifyToken(() -> asListHtml());
@@ -200,6 +206,7 @@ public class AdminDesignAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public StreamResponse download(final FileAccessForm form) {
         final File file = getTargetFile(form.fileName).get();
         if (file == null) {
@@ -216,6 +223,7 @@ public class AdminDesignAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final FileAccessForm form) {
         getTargetFile(form.fileName).ifPresent(file -> {
             if (!file.delete()) {
@@ -235,6 +243,7 @@ public class AdminDesignAction extends FessAdminAction {
     //                                                 Edit
     //                                                ------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         final String jspType = "view";
         final File jspFile = getJspFile(form.fileName, jspType);
@@ -248,6 +257,7 @@ public class AdminDesignAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse editAsUseDefault(final EditForm form) {
         final String jspType = "orig/view";
         final File jspFile = getJspFile(form.fileName, jspType);
@@ -261,6 +271,7 @@ public class AdminDesignAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         final String jspType = "view";
         final File jspFile = getJspFile(form.fileName, jspType);
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dict/AdminDictAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dict/AdminDictAction.java
index 825f3a3142f1e0a7aa7cbd5518d18c6d4d862407..1fcc681d3d839c18f54162ef9f588d46cbb2c0b3 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dict/AdminDictAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dict/AdminDictAction.java
@@ -17,6 +17,7 @@ package org.codelibs.fess.app.web.admin.dict;
 
 import javax.annotation.Resource;
 
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.dict.DictionaryFile;
 import org.codelibs.fess.dict.DictionaryItem;
@@ -31,6 +32,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminDictAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dict";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -50,6 +53,7 @@ public class AdminDictAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asHtml(path_AdminDict_AdminDictJsp).renderWith(data -> {
             final DictionaryFile<? extends DictionaryItem>[] dictFiles = dictionaryManager.getDictionaryFiles();
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dict/kuromoji/AdminDictKuromojiAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dict/kuromoji/AdminDictKuromojiAction.java
index fc9620c6360f655ae620b137f3a3e781970634cf..0b223e1142290534610b5a6b2263a6ee3f65243f 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dict/kuromoji/AdminDictKuromojiAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dict/kuromoji/AdminDictKuromojiAction.java
@@ -28,6 +28,7 @@ import org.codelibs.fess.app.pager.KuromojiPager;
 import org.codelibs.fess.app.service.KuromojiService;
 import org.codelibs.fess.app.web.CrudMode;
 import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.base.FessBaseAction;
 import org.codelibs.fess.dict.kuromoji.KuromojiItem;
@@ -49,6 +50,8 @@ import org.lastaflute.web.validation.exception.ValidationErrorException;
  */
 public class AdminDictKuromojiAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dict";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -70,6 +73,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         kuromojiPager.clear();
@@ -79,6 +83,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         pageNumber.ifPresent(num -> {
@@ -92,6 +97,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         copyBeanToBean(form, kuromojiPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -101,6 +107,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         kuromojiPager.clear();
@@ -126,6 +133,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictKuromoji_AdminDictKuromojiEditJsp).useForm(CreateForm.class, op -> {
@@ -138,6 +146,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.dictId));
         kuromojiService
@@ -164,6 +173,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
         saveToken();
@@ -193,6 +203,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse downloadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictKuromoji_AdminDictKuromojiDownloadJsp).useForm(DownloadForm.class, op -> {
@@ -209,6 +220,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final DownloadForm form) {
         validate(form, messages -> {}, () -> downloadpage(form.dictId));
         verifyTokenKeep(() -> downloadpage(form.dictId));
@@ -226,6 +238,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictKuromoji_AdminDictKuromojiUploadJsp).useForm(UploadForm.class, op -> {
@@ -242,6 +255,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> uploadpage(form.dictId));
         verifyToken(() -> uploadpage(form.dictId));
@@ -266,6 +280,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -286,6 +301,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -306,6 +322,7 @@ public class AdminDictKuromojiAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dict/mapping/AdminDictMappingAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dict/mapping/AdminDictMappingAction.java
index bd665550fa6524e6ebbb299f0b59617c7b7527fd..039aa3388b3fdd82e8773cd48751172336726168 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dict/mapping/AdminDictMappingAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dict/mapping/AdminDictMappingAction.java
@@ -30,6 +30,7 @@ import org.codelibs.fess.app.pager.CharMappingPager;
 import org.codelibs.fess.app.service.CharMappingService;
 import org.codelibs.fess.app.web.CrudMode;
 import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.base.FessBaseAction;
 import org.codelibs.fess.dict.mapping.CharMappingItem;
@@ -51,6 +52,8 @@ import org.lastaflute.web.validation.exception.ValidationErrorException;
  */
 public class AdminDictMappingAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dict";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -72,6 +75,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         charMappingPager.clear();
@@ -81,6 +85,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         pageNumber.ifPresent(num -> {
@@ -94,6 +99,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         copyBeanToBean(form, charMappingPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -103,6 +109,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         charMappingPager.clear();
@@ -128,6 +135,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictMapping_AdminDictMappingEditJsp).useForm(CreateForm.class, op -> {
@@ -140,6 +148,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.dictId));
         charMappingService
@@ -167,6 +176,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
         saveToken();
@@ -196,6 +206,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse downloadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictMapping_AdminDictMappingDownloadJsp).useForm(DownloadForm.class, op -> {
@@ -212,6 +223,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final DownloadForm form) {
         validate(form, messages -> {}, () -> downloadpage(form.dictId));
         verifyTokenKeep(() -> downloadpage(form.dictId));
@@ -229,6 +241,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictMapping_AdminDictMappingUploadJsp).useForm(UploadForm.class, op -> {
@@ -245,6 +258,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> uploadpage(form.dictId));
         verifyToken(() -> uploadpage(form.dictId));
@@ -269,6 +283,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -289,6 +304,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -309,6 +325,7 @@ public class AdminDictMappingAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dict/protwords/AdminDictProtwordsAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dict/protwords/AdminDictProtwordsAction.java
index ff5ca5ee6e69302c71996f2c8bb04bb597ab940b..ccc97a931c13eaae2751dc58aac22f2efd8fdbce 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dict/protwords/AdminDictProtwordsAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dict/protwords/AdminDictProtwordsAction.java
@@ -28,6 +28,7 @@ import org.codelibs.fess.app.pager.ProtwordsPager;
 import org.codelibs.fess.app.service.ProtwordsService;
 import org.codelibs.fess.app.web.CrudMode;
 import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.base.FessBaseAction;
 import org.codelibs.fess.dict.protwords.ProtwordsItem;
@@ -48,6 +49,8 @@ import org.lastaflute.web.validation.exception.ValidationErrorException;
  */
 public class AdminDictProtwordsAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dict";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -69,6 +72,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         protwordsPager.clear();
@@ -78,6 +82,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         pageNumber.ifPresent(num -> {
@@ -91,6 +96,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         copyBeanToBean(form, protwordsPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -100,6 +106,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         protwordsPager.clear();
@@ -125,6 +132,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictProtwords_AdminDictProtwordsEditJsp).useForm(CreateForm.class, op -> {
@@ -137,6 +145,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.dictId));
         protwordsService
@@ -163,6 +172,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
         saveToken();
@@ -191,6 +201,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse downloadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictProtwords_AdminDictProtwordsDownloadJsp).useForm(DownloadForm.class, op -> {
@@ -207,6 +218,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final DownloadForm form) {
         validate(form, messages -> {}, () -> downloadpage(form.dictId));
         verifyTokenKeep(() -> downloadpage(form.dictId));
@@ -224,6 +236,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictProtwords_AdminDictProtwordsUploadJsp).useForm(UploadForm.class, op -> {
@@ -240,6 +253,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> uploadpage(form.dictId));
         verifyToken(() -> uploadpage(form.dictId));
@@ -264,6 +278,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -276,6 +291,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -290,6 +306,7 @@ public class AdminDictProtwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dict/stemmeroverride/AdminDictStemmeroverrideAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dict/stemmeroverride/AdminDictStemmeroverrideAction.java
index ef93f4b0f4c66c76bb1dd4a9548a92765b1d6b2e..5ce0d44eba6aeb328aff86cc524934d264e40ace 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dict/stemmeroverride/AdminDictStemmeroverrideAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dict/stemmeroverride/AdminDictStemmeroverrideAction.java
@@ -28,6 +28,7 @@ import org.codelibs.fess.app.pager.StemmerOverridePager;
 import org.codelibs.fess.app.service.StemmerOverrideService;
 import org.codelibs.fess.app.web.CrudMode;
 import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.base.FessBaseAction;
 import org.codelibs.fess.dict.stemmeroverride.StemmerOverrideItem;
@@ -48,6 +49,8 @@ import org.lastaflute.web.validation.exception.ValidationErrorException;
  */
 public class AdminDictStemmeroverrideAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dict";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -69,6 +72,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         stemmerOverridePager.clear();
@@ -78,6 +82,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         pageNumber.ifPresent(num -> {
@@ -91,6 +96,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         copyBeanToBean(form, stemmerOverridePager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -100,6 +106,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         stemmerOverridePager.clear();
@@ -126,6 +133,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideEditJsp).useForm(CreateForm.class, op -> {
@@ -138,6 +146,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.dictId));
         stemmerOverrideService
@@ -165,6 +174,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
         saveToken();
@@ -194,6 +204,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse downloadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideDownloadJsp).useForm(DownloadForm.class, op -> {
@@ -210,6 +221,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final DownloadForm form) {
         validate(form, messages -> {}, () -> downloadpage(form.dictId));
         verifyTokenKeep(() -> downloadpage(form.dictId));
@@ -232,6 +244,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictStemmeroverride_AdminDictStemmeroverrideUploadJsp).useForm(UploadForm.class, op -> {
@@ -248,6 +261,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> uploadpage(form.dictId));
         verifyToken(() -> uploadpage(form.dictId));
@@ -272,6 +286,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -292,6 +307,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -313,6 +329,7 @@ public class AdminDictStemmeroverrideAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dict/stopwords/AdminDictStopwordsAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dict/stopwords/AdminDictStopwordsAction.java
index 1a290a22afe4f4e625059ee9518573dd6f5da725..6fefcf6727c2dfc2dd4e317998b1ac82610a5f51 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dict/stopwords/AdminDictStopwordsAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dict/stopwords/AdminDictStopwordsAction.java
@@ -28,6 +28,7 @@ import org.codelibs.fess.app.pager.StopwordsPager;
 import org.codelibs.fess.app.service.StopwordsService;
 import org.codelibs.fess.app.web.CrudMode;
 import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.dict.stopwords.StopwordsItem;
 import org.codelibs.fess.util.ComponentUtil;
@@ -46,6 +47,8 @@ import org.lastaflute.web.validation.VaErrorHook;
  */
 public class AdminDictStopwordsAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dict";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -67,6 +70,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         stopwordsPager.clear();
@@ -76,6 +80,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         pageNumber.ifPresent(num -> {
@@ -89,6 +94,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         copyBeanToBean(form, stopwordsPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -98,6 +104,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         stopwordsPager.clear();
@@ -123,6 +130,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictStopwords_AdminDictStopwordsEditJsp).useForm(CreateForm.class, op -> {
@@ -135,6 +143,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.dictId));
         stopwordsService
@@ -161,6 +170,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
         saveToken();
@@ -189,6 +199,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse downloadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictStopwords_AdminDictStopwordsDownloadJsp).useForm(DownloadForm.class, op -> {
@@ -205,6 +216,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final DownloadForm form) {
         validate(form, messages -> {}, () -> downloadpage(form.dictId));
         verifyTokenKeep(() -> downloadpage(form.dictId));
@@ -222,6 +234,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictStopwords_AdminDictStopwordsUploadJsp).useForm(UploadForm.class, op -> {
@@ -238,6 +251,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> uploadpage(form.dictId));
         verifyToken(() -> uploadpage(form.dictId));
@@ -262,6 +276,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -274,6 +289,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -288,6 +304,7 @@ public class AdminDictStopwordsAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/dict/synonym/AdminDictSynonymAction.java b/src/main/java/org/codelibs/fess/app/web/admin/dict/synonym/AdminDictSynonymAction.java
index 6002971a5b8db437153bf6fdf600641487ab2d1d..180c21b1861c34de965ab438c655ebd2ff6de3c3 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/dict/synonym/AdminDictSynonymAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/dict/synonym/AdminDictSynonymAction.java
@@ -30,6 +30,7 @@ import org.codelibs.fess.app.pager.SynonymPager;
 import org.codelibs.fess.app.service.SynonymService;
 import org.codelibs.fess.app.web.CrudMode;
 import org.codelibs.fess.app.web.admin.dict.AdminDictAction;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.base.FessBaseAction;
 import org.codelibs.fess.dict.synonym.SynonymItem;
@@ -51,6 +52,8 @@ import org.lastaflute.web.validation.exception.ValidationErrorException;
  */
 public class AdminDictSynonymAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-dict";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -72,6 +75,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         synonymPager.clear();
@@ -81,6 +85,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         pageNumber.ifPresent(num -> {
@@ -94,6 +99,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         copyBeanToBean(form, synonymPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -103,6 +109,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         validate(form, messages -> {}, () -> asDictIndexHtml());
         synonymPager.clear();
@@ -128,6 +135,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictSynonym_AdminDictSynonymEditJsp).useForm(CreateForm.class, op -> {
@@ -140,6 +148,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.dictId));
         synonymService
@@ -167,6 +176,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final String dictId, final int crudMode, final long id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS, dictId);
         saveToken();
@@ -196,6 +206,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse downloadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictSynonym_AdminDictSynonymDownloadJsp).useForm(DownloadForm.class, op -> {
@@ -212,6 +223,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final DownloadForm form) {
         validate(form, messages -> {}, () -> downloadpage(form.dictId));
         verifyTokenKeep(() -> downloadpage(form.dictId));
@@ -229,6 +241,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage(final String dictId) {
         saveToken();
         return asHtml(path_AdminDictSynonym_AdminDictSynonymUploadJsp).useForm(UploadForm.class, op -> {
@@ -245,6 +258,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> uploadpage(form.dictId));
         verifyToken(() -> uploadpage(form.dictId));
@@ -269,6 +283,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -289,6 +304,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT, form.dictId);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -310,6 +326,7 @@ public class AdminDictSynonymAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS, form.dictId);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/duplicatehost/AdminDuplicatehostAction.java b/src/main/java/org/codelibs/fess/app/web/admin/duplicatehost/AdminDuplicatehostAction.java
index 1b460f0fe664d1d156b9e9e79f6f55060cff6aeb..819d23742744c397c960fb3cb331b6b32a16bc6d 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/duplicatehost/AdminDuplicatehostAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/duplicatehost/AdminDuplicatehostAction.java
@@ -21,6 +21,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.DuplicateHostPager;
 import org.codelibs.fess.app.service.DuplicateHostService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.DuplicateHost;
 import org.codelibs.fess.helper.SystemHelper;
@@ -39,6 +40,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminDuplicatehostAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-duplicatehost";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -60,11 +63,13 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             duplicateHostPager.setCurrentPageNumber(pageNumber.get());
@@ -77,6 +82,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, duplicateHostPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostJsp).renderWith(data -> {
@@ -85,6 +91,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         duplicateHostPager.clear();
         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostJsp).renderWith(data -> {
@@ -106,6 +113,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminDuplicatehost_AdminDuplicatehostEditJsp).useForm(CreateForm.class, op -> {
@@ -117,6 +125,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -140,6 +149,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -161,6 +171,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -181,6 +192,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -201,6 +213,7 @@ public class AdminDuplicatehostAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/elevateword/AdminElevatewordAction.java b/src/main/java/org/codelibs/fess/app/web/admin/elevateword/AdminElevatewordAction.java
index c33fe687bf9cc794a86e093db5a49434caeec494..0ee802a5145720eeb932a98d0e17ddcdfadb98d3 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/elevateword/AdminElevatewordAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/elevateword/AdminElevatewordAction.java
@@ -40,6 +40,7 @@ import org.codelibs.fess.app.pager.ElevateWordPager;
 import org.codelibs.fess.app.service.ElevateWordService;
 import org.codelibs.fess.app.service.LabelTypeService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.ElevateWord;
 import org.codelibs.fess.exception.FessSystemException;
@@ -61,6 +62,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminElevatewordAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-elevateword";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -86,11 +89,13 @@ public class AdminElevatewordAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             elevateWordPager.setCurrentPageNumber(pageNumber.get());
@@ -103,6 +108,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, elevateWordPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminElevateword_AdminElevatewordJsp).renderWith(data -> {
@@ -111,6 +117,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         elevateWordPager.clear();
         return asHtml(path_AdminElevateword_AdminElevatewordJsp).renderWith(data -> {
@@ -132,6 +139,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminElevateword_AdminElevatewordEditJsp).useForm(CreateForm.class, op -> {
@@ -145,6 +153,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -179,6 +188,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -209,12 +219,14 @@ public class AdminElevatewordAction extends FessAdminAction {
     //                                              Download
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse downloadpage() {
         saveToken();
         return asDownloadHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final DownloadForm form) {
         verifyToken(() -> asDownloadHtml());
 
@@ -239,6 +251,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     //                                                Upload
     //                                               -------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse uploadpage() {
         saveToken();
         return asUploadHtml();
@@ -248,6 +261,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -270,6 +284,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -292,6 +307,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
@@ -317,6 +333,7 @@ public class AdminElevatewordAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> asUploadHtml());
         verifyToken(() -> asUploadHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/esreq/AdminEsreqAction.java b/src/main/java/org/codelibs/fess/app/web/admin/esreq/AdminEsreqAction.java
index e3e067e97badee044a43593fa23170fe1e03069a..8ba314eb2f99ff46db5df35243bd61e7fc2ee2d2 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/esreq/AdminEsreqAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/esreq/AdminEsreqAction.java
@@ -30,6 +30,7 @@ import org.codelibs.core.lang.StringUtil;
 import org.codelibs.curl.CurlRequest;
 import org.codelibs.curl.CurlResponse;
 import org.codelibs.fess.Constants;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.helper.CurlHelper;
 import org.codelibs.fess.util.ComponentUtil;
@@ -43,6 +44,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminEsreqAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-esreq";
+
     private static final Logger logger = LogManager.getLogger(AdminEsreqAction.class);
 
     @Override
@@ -52,11 +55,13 @@ public class AdminEsreqAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml(() -> saveToken());
     }
 
     @Execute
+    @Secured({ ROLE })
     public ActionResponse upload(final UploadForm form) {
         validate(form, messages -> {}, () -> asListHtml(null));
         verifyToken(() -> asListHtml(() -> saveToken()));
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/failureurl/AdminFailureurlAction.java b/src/main/java/org/codelibs/fess/app/web/admin/failureurl/AdminFailureurlAction.java
index 994c9b47adcced590cf3b80aa6927efe6eb03382..e60ec6e5d96ea0752d75e2f54a675ade571560b9 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/failureurl/AdminFailureurlAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/failureurl/AdminFailureurlAction.java
@@ -21,6 +21,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.FailureUrlPager;
 import org.codelibs.fess.app.service.FailureUrlService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.util.RenderDataUtil;
 import org.lastaflute.web.Execute;
@@ -34,6 +35,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminFailureurlAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-failureurl";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -55,12 +58,14 @@ public class AdminFailureurlAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final Integer pageNumber, final SearchForm form) {
         failureUrlPager.setCurrentPageNumber(pageNumber);
         return asHtml(path_AdminFailureurl_AdminFailureurlJsp).renderWith(data -> {
@@ -69,6 +74,7 @@ public class AdminFailureurlAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, failureUrlPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminFailureurl_AdminFailureurlJsp).renderWith(data -> {
@@ -77,6 +83,7 @@ public class AdminFailureurlAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         failureUrlPager.clear();
         return asHtml(path_AdminFailureurl_AdminFailureurlJsp).renderWith(data -> {
@@ -85,6 +92,7 @@ public class AdminFailureurlAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse back(final SearchForm form) {
         return asHtml(path_AdminFailureurl_AdminFailureurlJsp).renderWith(data -> {
             searchPaging(data, form);
@@ -102,6 +110,7 @@ public class AdminFailureurlAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         return asHtml(path_AdminFailureurl_AdminFailureurlDetailsJsp).useForm(EditForm.class, op -> {
@@ -123,6 +132,7 @@ public class AdminFailureurlAction extends FessAdminAction {
     //                                         -------------
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
@@ -136,6 +146,7 @@ public class AdminFailureurlAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse deleteall() {
         verifyToken(() -> asListHtml());
         failureUrlService.deleteAll(failureUrlPager);
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/fileauth/AdminFileauthAction.java b/src/main/java/org/codelibs/fess/app/web/admin/fileauth/AdminFileauthAction.java
index c71f3009c55691b57c55688ef1e9639a39447708..503402b29864ffd4bd5231daa98e301dd2009080 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/fileauth/AdminFileauthAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/fileauth/AdminFileauthAction.java
@@ -28,6 +28,7 @@ import org.codelibs.fess.app.pager.FileAuthPager;
 import org.codelibs.fess.app.service.FileAuthenticationService;
 import org.codelibs.fess.app.service.FileConfigService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.FileAuthentication;
 import org.codelibs.fess.es.config.exentity.FileConfig;
@@ -47,6 +48,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminFileauthAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-fileauth";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -71,11 +74,13 @@ public class AdminFileauthAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             fileAuthenticationPager.setCurrentPageNumber(pageNumber.get());
@@ -88,6 +93,7 @@ public class AdminFileauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, fileAuthenticationPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminFileauth_AdminFileauthJsp).renderWith(data -> {
@@ -96,6 +102,7 @@ public class AdminFileauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         fileAuthenticationPager.clear();
         return asHtml(path_AdminFileauth_AdminFileauthJsp).renderWith(data -> {
@@ -118,6 +125,7 @@ public class AdminFileauthAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminFileauth_AdminFileauthEditJsp).useForm(CreateForm.class, op -> {
@@ -132,6 +140,7 @@ public class AdminFileauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -155,6 +164,7 @@ public class AdminFileauthAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -176,6 +186,7 @@ public class AdminFileauthAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -196,6 +207,7 @@ public class AdminFileauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -216,6 +228,7 @@ public class AdminFileauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/fileconfig/AdminFileconfigAction.java b/src/main/java/org/codelibs/fess/app/web/admin/fileconfig/AdminFileconfigAction.java
index eeb37b50b4f4f3a52731879208f912ec17b878fc..6d61b5f4efe8f34b9867e14f142b305b5da1b13c 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/fileconfig/AdminFileconfigAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/fileconfig/AdminFileconfigAction.java
@@ -30,6 +30,7 @@ import org.codelibs.fess.app.service.FileConfigService;
 import org.codelibs.fess.app.service.LabelTypeService;
 import org.codelibs.fess.app.service.RoleTypeService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.FileConfig;
 import org.codelibs.fess.helper.PermissionHelper;
@@ -49,6 +50,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminFileconfigAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-fileconfig";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -74,11 +77,13 @@ public class AdminFileconfigAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             fileConfigPager.setCurrentPageNumber(pageNumber.get());
@@ -91,6 +96,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, fileConfigPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminFileconfig_AdminFileconfigJsp).renderWith(data -> {
@@ -99,6 +105,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         fileConfigPager.clear();
         return asHtml(path_AdminFileconfig_AdminFileconfigJsp).renderWith(data -> {
@@ -120,6 +127,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminFileconfig_AdminFileconfigEditJsp).useForm(CreateForm.class, op -> {
@@ -133,6 +141,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final PermissionHelper permissionHelper = ComponentUtil.getPermissionHelper();
@@ -170,6 +179,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -205,6 +215,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -225,6 +236,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -245,6 +257,7 @@ public class AdminFileconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/general/AdminGeneralAction.java b/src/main/java/org/codelibs/fess/app/web/admin/general/AdminGeneralAction.java
index d119d2edc606dbfbfc82eb657bcfcf9559396276..1835ab1efcdfaefceb67c087b7f8bed7d65f35b4 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/general/AdminGeneralAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/general/AdminGeneralAction.java
@@ -30,6 +30,7 @@ import org.codelibs.core.beans.util.BeanUtil;
 import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.DynamicProperties;
 import org.codelibs.fess.Constants;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.helper.SystemHelper;
 import org.codelibs.fess.mylasta.direction.FessConfig;
@@ -46,6 +47,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminGeneralAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-general";
+
     private static final String DUMMY_PASSWORD = "**********";
 
     private static final Logger logger = LogManager.getLogger(AdminGeneralAction.class);
@@ -70,6 +73,7 @@ public class AdminGeneralAction extends FessAdminAction {
     //
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asHtml(path_AdminGeneral_AdminGeneralJsp).useForm(EditForm.class, setup -> {
@@ -80,6 +84,7 @@ public class AdminGeneralAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse sendmail(final MailForm form) {
         validate(form, messages -> {}, () -> {
             return asHtml(path_AdminGeneral_AdminGeneralJsp);
@@ -112,6 +117,7 @@ public class AdminGeneralAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         validate(form, messages -> {}, () -> {
             return asHtml(path_AdminGeneral_AdminGeneralJsp);
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/group/AdminGroupAction.java b/src/main/java/org/codelibs/fess/app/web/admin/group/AdminGroupAction.java
index b14dfe8dfc28202ae60349cf9fb1ecb728cfbf6e..80bb39297755b4996764d8e442b034a0342eafa9 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/group/AdminGroupAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/group/AdminGroupAction.java
@@ -25,6 +25,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.GroupPager;
 import org.codelibs.fess.app.service.GroupService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.user.exentity.Group;
 import org.codelibs.fess.util.ComponentUtil;
@@ -42,6 +43,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminGroupAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-group";
+
     private static final Logger logger = LogManager.getLogger(AdminGroupAction.class);
 
     // ===================================================================================
@@ -65,11 +68,13 @@ public class AdminGroupAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             groupPager.setCurrentPageNumber(pageNumber.get());
@@ -82,6 +87,7 @@ public class AdminGroupAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, groupPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminGroup_AdminGroupJsp).renderWith(data -> {
@@ -90,6 +96,7 @@ public class AdminGroupAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         groupPager.clear();
         return asHtml(path_AdminGroup_AdminGroupJsp).renderWith(data -> {
@@ -111,6 +118,7 @@ public class AdminGroupAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminGroup_AdminGroupEditJsp).useForm(CreateForm.class, op -> {
@@ -122,6 +130,7 @@ public class AdminGroupAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -145,6 +154,7 @@ public class AdminGroupAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -166,6 +176,7 @@ public class AdminGroupAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -187,6 +198,7 @@ public class AdminGroupAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -208,6 +220,7 @@ public class AdminGroupAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/joblog/AdminJoblogAction.java b/src/main/java/org/codelibs/fess/app/web/admin/joblog/AdminJoblogAction.java
index 10c89f5e0bd31af9ed641f1cc2d271e3e4b544d3..4a4a3557cca84af567cc837a8a1adf3d4a438541 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/joblog/AdminJoblogAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/joblog/AdminJoblogAction.java
@@ -24,6 +24,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.JobLogPager;
 import org.codelibs.fess.app.service.JobLogService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.util.RenderDataUtil;
 import org.lastaflute.web.Execute;
@@ -37,6 +38,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminJoblogAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-joblog";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -58,12 +61,14 @@ public class AdminJoblogAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         saveToken();
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final Integer pageNumber, final SearchForm form) {
         saveToken();
         jobLogPager.setCurrentPageNumber(pageNumber);
@@ -73,6 +78,7 @@ public class AdminJoblogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         saveToken();
         copyBeanToBean(form, jobLogPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
@@ -82,6 +88,7 @@ public class AdminJoblogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         saveToken();
         jobLogPager.clear();
@@ -91,6 +98,7 @@ public class AdminJoblogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse back(final SearchForm form) {
         saveToken();
         return asHtml(path_AdminJoblog_AdminJoblogJsp).renderWith(data -> {
@@ -116,6 +124,7 @@ public class AdminJoblogAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -137,6 +146,7 @@ public class AdminJoblogAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
@@ -150,6 +160,7 @@ public class AdminJoblogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse deleteall() {
         verifyToken(() -> asListHtml());
         final List<String> jobStatusList = new ArrayList<>();
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/keymatch/AdminKeymatchAction.java b/src/main/java/org/codelibs/fess/app/web/admin/keymatch/AdminKeymatchAction.java
index 9f3b32ec203465459645f7d2ec4fa71144cc821a..5a4c5b207fdbcd1138093e93b4e51ddee1e6ede1 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/keymatch/AdminKeymatchAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/keymatch/AdminKeymatchAction.java
@@ -25,6 +25,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.KeyMatchPager;
 import org.codelibs.fess.app.service.KeyMatchService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.KeyMatch;
 import org.codelibs.fess.helper.KeyMatchHelper;
@@ -44,6 +45,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminKeymatchAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-keymatch";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -67,11 +70,13 @@ public class AdminKeymatchAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             keyMatchPager.setCurrentPageNumber(pageNumber.get());
@@ -84,6 +89,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, keyMatchPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminKeymatch_AdminKeymatchJsp).renderWith(data -> {
@@ -92,6 +98,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         keyMatchPager.clear();
         return asHtml(path_AdminKeymatch_AdminKeymatchJsp).renderWith(data -> {
@@ -113,6 +120,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminKeymatch_AdminKeymatchEditJsp).useForm(CreateForm.class, op -> {
@@ -124,6 +132,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -147,6 +156,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -172,6 +182,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -193,6 +204,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -214,6 +226,7 @@ public class AdminKeymatchAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/labeltype/AdminLabeltypeAction.java b/src/main/java/org/codelibs/fess/app/web/admin/labeltype/AdminLabeltypeAction.java
index 79e5f4c31d4246d18c777a50b67eaa17574fd2ae..a095eba937fea73b529657c6520e1c5ef7e888f9 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/labeltype/AdminLabeltypeAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/labeltype/AdminLabeltypeAction.java
@@ -29,6 +29,7 @@ import org.codelibs.fess.app.pager.LabelTypePager;
 import org.codelibs.fess.app.service.LabelTypeService;
 import org.codelibs.fess.app.service.RoleTypeService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.LabelType;
 import org.codelibs.fess.helper.PermissionHelper;
@@ -49,6 +50,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminLabeltypeAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-labeltype";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -72,11 +75,13 @@ public class AdminLabeltypeAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             labelTypePager.setCurrentPageNumber(pageNumber.get());
@@ -89,6 +94,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, labelTypePager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminLabeltype_AdminLabeltypeJsp).renderWith(data -> {
@@ -97,6 +103,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         labelTypePager.clear();
         return asHtml(path_AdminLabeltype_AdminLabeltypeJsp).renderWith(data -> {
@@ -118,6 +125,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminLabeltype_AdminLabeltypeEditJsp).useForm(CreateForm.class, op -> {
@@ -131,6 +139,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -165,6 +174,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -202,6 +212,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -222,6 +233,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -242,6 +254,7 @@ public class AdminLabeltypeAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/log/AdminLogAction.java b/src/main/java/org/codelibs/fess/app/web/admin/log/AdminLogAction.java
index ecbb7019866f6246cca603cbfeea390d2b8e9076..dc25bee7d46469cbb1bedd1e005161138470a7dd 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/log/AdminLogAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/log/AdminLogAction.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import java.util.stream.Stream;
 
 import org.codelibs.core.lang.StringUtil;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.exception.FessSystemException;
 import org.codelibs.fess.helper.SystemHelper;
@@ -47,6 +48,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminLogAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-log";
+
     @Override
     protected void setupHtmlData(final ActionRuntime runtime) {
         super.setupHtmlData(runtime);
@@ -54,11 +57,13 @@ public class AdminLogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asIndexHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final String id) {
         final String filename = new String(Base64.getDecoder().decode(id), StandardCharsets.UTF_8).replace("..", "").replaceAll("\\s", "");
         final String logFilePath = systemHelper.getLogFilePath();
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/maintenance/AdminMaintenanceAction.java b/src/main/java/org/codelibs/fess/app/web/admin/maintenance/AdminMaintenanceAction.java
index 36e06ec59fd9d215726560837d8d950d337aead6..924c811cd11b780a08e6d196394369049d8dd227 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/maintenance/AdminMaintenanceAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/maintenance/AdminMaintenanceAction.java
@@ -36,6 +36,7 @@ import org.codelibs.core.io.CopyUtil;
 import org.codelibs.core.lang.StringUtil;
 import org.codelibs.curl.CurlResponse;
 import org.codelibs.fess.Constants;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.client.FessEsClient;
 import org.codelibs.fess.mylasta.direction.FessConfig.SimpleImpl;
@@ -48,6 +49,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
 
 public class AdminMaintenanceAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-maintenance";
+
     // ===================================================================================
     //                                                                            Constant
     //
@@ -78,6 +81,7 @@ public class AdminMaintenanceAction extends FessAdminAction {
     //                                                                      ==============
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asIndexHtml();
@@ -91,6 +95,7 @@ public class AdminMaintenanceAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse reindexOnly(final ActionForm form) {
         validate(form, messages -> {}, this::asIndexHtml);
         verifyToken(this::asIndexHtml);
@@ -102,6 +107,7 @@ public class AdminMaintenanceAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse reloadDocIndex(final ActionForm form) {
         validate(form, messages -> {}, this::asIndexHtml);
         verifyToken(this::asIndexHtml);
@@ -127,6 +133,7 @@ public class AdminMaintenanceAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse clearCrawlerIndex(final ActionForm form) {
         validate(form, messages -> {}, this::asIndexHtml);
         verifyToken(this::asIndexHtml);
@@ -145,6 +152,7 @@ public class AdminMaintenanceAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse downloadLogs(final ActionForm form) {
         validate(form, messages -> {}, this::asIndexHtml);
         verifyTokenKeep(this::asIndexHtml);
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/pathmap/AdminPathmapAction.java b/src/main/java/org/codelibs/fess/app/web/admin/pathmap/AdminPathmapAction.java
index bf1404f77b78b64cc0ebd7ca49b17224d232feca..8cb08a3cf38e08a6219cfaadf7a1fa3bcfe889eb 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/pathmap/AdminPathmapAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/pathmap/AdminPathmapAction.java
@@ -21,6 +21,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.PathMapPager;
 import org.codelibs.fess.app.service.PathMappingService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.PathMapping;
 import org.codelibs.fess.helper.SystemHelper;
@@ -40,6 +41,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminPathmapAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-pathmap";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -61,11 +64,13 @@ public class AdminPathmapAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             pathMapPager.setCurrentPageNumber(pageNumber.get());
@@ -78,6 +83,7 @@ public class AdminPathmapAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, pathMapPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminPathmap_AdminPathmapJsp).renderWith(data -> {
@@ -86,6 +92,7 @@ public class AdminPathmapAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         pathMapPager.clear();
         return asHtml(path_AdminPathmap_AdminPathmapJsp).renderWith(data -> {
@@ -107,6 +114,7 @@ public class AdminPathmapAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminPathmap_AdminPathmapEditJsp).useForm(CreateForm.class, op -> {
@@ -118,6 +126,7 @@ public class AdminPathmapAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -141,6 +150,7 @@ public class AdminPathmapAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -162,6 +172,7 @@ public class AdminPathmapAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -182,6 +193,7 @@ public class AdminPathmapAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -202,6 +214,7 @@ public class AdminPathmapAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/plugin/AdminPluginAction.java b/src/main/java/org/codelibs/fess/app/web/admin/plugin/AdminPluginAction.java
index 7f8a50ce18b7cf4544a996ea9c7ad06864269ef0..4d06e62a8d1bf3a2942963a0117a96f566e488d3 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/plugin/AdminPluginAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/plugin/AdminPluginAction.java
@@ -29,6 +29,7 @@ import java.util.stream.Collectors;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.codelibs.core.io.CopyUtil;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.helper.PluginHelper;
 import org.codelibs.fess.helper.PluginHelper.Artifact;
@@ -41,6 +42,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
 
 public class AdminPluginAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-plugin";
+
     private static final Logger logger = LogManager.getLogger(AdminPluginAction.class);
 
     private static final String UPLOAD = "upload";
@@ -52,12 +55,14 @@ public class AdminPluginAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final DeleteForm form) {
         validate(form, messages -> {}, () -> asHtml(path_AdminPlugin_AdminPluginJsp));
         verifyToken(() -> asHtml(path_AdminPlugin_AdminPluginJsp));
@@ -68,6 +73,7 @@ public class AdminPluginAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse install(final InstallForm form) {
         validate(form, messages -> {}, () -> asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp));
         verifyToken(() -> asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp));
@@ -117,6 +123,7 @@ public class AdminPluginAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse installplugin() {
         saveToken();
         return asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp).renderWith(data -> {
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/relatedcontent/AdminRelatedcontentAction.java b/src/main/java/org/codelibs/fess/app/web/admin/relatedcontent/AdminRelatedcontentAction.java
index 9e619b234159ed97a98b045b5a4c8744394e4d19..f20630a576980727e6cac4aa0147f6be15496603 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/relatedcontent/AdminRelatedcontentAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/relatedcontent/AdminRelatedcontentAction.java
@@ -22,6 +22,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.RelatedContentPager;
 import org.codelibs.fess.app.service.RelatedContentService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.RelatedContent;
 import org.codelibs.fess.helper.SystemHelper;
@@ -39,6 +40,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminRelatedcontentAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-relatedcontent";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -60,11 +63,13 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             relatedContentPager.setCurrentPageNumber(pageNumber.get());
@@ -77,6 +82,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, relatedContentPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminRelatedcontent_AdminRelatedcontentJsp).renderWith(data -> {
@@ -85,6 +91,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         relatedContentPager.clear();
         return asHtml(path_AdminRelatedcontent_AdminRelatedcontentJsp).renderWith(data -> {
@@ -106,6 +113,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asEditHtml().useForm(CreateForm.class, op -> {
@@ -117,6 +125,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -140,6 +149,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -161,6 +171,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -181,6 +192,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -201,6 +213,7 @@ public class AdminRelatedcontentAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/relatedquery/AdminRelatedqueryAction.java b/src/main/java/org/codelibs/fess/app/web/admin/relatedquery/AdminRelatedqueryAction.java
index 5c7cef6779b26150b396b32ade78a020cb1af852..1c863f013102373e69db3dda03ee37e906d5857d 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/relatedquery/AdminRelatedqueryAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/relatedquery/AdminRelatedqueryAction.java
@@ -29,6 +29,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.RelatedQueryPager;
 import org.codelibs.fess.app.service.RelatedQueryService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.RelatedQuery;
 import org.codelibs.fess.helper.SystemHelper;
@@ -46,6 +47,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminRelatedqueryAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-relatedquery";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -67,11 +70,13 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             relatedQueryPager.setCurrentPageNumber(pageNumber.get());
@@ -84,6 +89,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, relatedQueryPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminRelatedquery_AdminRelatedqueryJsp).renderWith(data -> {
@@ -92,6 +98,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         relatedQueryPager.clear();
         return asHtml(path_AdminRelatedquery_AdminRelatedqueryJsp).renderWith(data -> {
@@ -113,6 +120,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asEditHtml().useForm(CreateForm.class, op -> {
@@ -124,6 +132,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -156,6 +165,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -189,6 +199,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -209,6 +220,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -229,6 +241,7 @@ public class AdminRelatedqueryAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/reqheader/AdminReqheaderAction.java b/src/main/java/org/codelibs/fess/app/web/admin/reqheader/AdminReqheaderAction.java
index 9f437a4fe6594da0b0f555056a078c544aa91be4..ff6b08e38c0aff48c85a53fc4591d097696f956d 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/reqheader/AdminReqheaderAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/reqheader/AdminReqheaderAction.java
@@ -27,6 +27,7 @@ import org.codelibs.fess.app.pager.ReqHeaderPager;
 import org.codelibs.fess.app.service.RequestHeaderService;
 import org.codelibs.fess.app.service.WebConfigService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.RequestHeader;
 import org.codelibs.fess.es.config.exentity.WebConfig;
@@ -47,6 +48,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminReqheaderAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-reqheader";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -70,11 +73,13 @@ public class AdminReqheaderAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             reqHeaderPager.setCurrentPageNumber(pageNumber.get());
@@ -87,6 +92,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, reqHeaderPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminReqheader_AdminReqheaderJsp).renderWith(data -> {
@@ -95,6 +101,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         reqHeaderPager.clear();
         return asHtml(path_AdminReqheader_AdminReqheaderJsp).renderWith(data -> {
@@ -117,6 +124,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminReqheader_AdminReqheaderEditJsp).useForm(CreateForm.class, op -> {
@@ -130,6 +138,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -153,6 +162,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -174,6 +184,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -194,6 +205,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -214,6 +226,7 @@ public class AdminReqheaderAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/role/AdminRoleAction.java b/src/main/java/org/codelibs/fess/app/web/admin/role/AdminRoleAction.java
index 7d96c7c51dc1bfe0996f2d48832e4bbf85fe5e05..91b0a6730a116cebefeb632b917ece40624e2a42 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/role/AdminRoleAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/role/AdminRoleAction.java
@@ -25,6 +25,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.RolePager;
 import org.codelibs.fess.app.service.RoleService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.user.exentity.Role;
 import org.codelibs.fess.util.ComponentUtil;
@@ -42,6 +43,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminRoleAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-role";
+
     private static final Logger logger = LogManager.getLogger(AdminRoleAction.class);
 
     // ===================================================================================
@@ -65,11 +68,13 @@ public class AdminRoleAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             rolePager.setCurrentPageNumber(pageNumber.get());
@@ -82,6 +87,7 @@ public class AdminRoleAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, rolePager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminRole_AdminRoleJsp).renderWith(data -> {
@@ -90,6 +96,7 @@ public class AdminRoleAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         rolePager.clear();
         return asHtml(path_AdminRole_AdminRoleJsp).renderWith(data -> {
@@ -111,6 +118,7 @@ public class AdminRoleAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminRole_AdminRoleEditJsp).useForm(CreateForm.class, op -> {
@@ -125,6 +133,7 @@ public class AdminRoleAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -146,6 +155,7 @@ public class AdminRoleAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -167,6 +177,7 @@ public class AdminRoleAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java b/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java
index c1024e6fce87618f74395985e7861b266ae7b767..2d897154dbd7cb3bf8b1c592f9356ba247b7921a 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java
@@ -24,6 +24,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.SchedulerPager;
 import org.codelibs.fess.app.service.ScheduledJobService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.ScheduledJob;
 import org.codelibs.fess.helper.ProcessHelper;
@@ -44,6 +45,8 @@ import org.lastaflute.web.util.LaRequestUtil;
  */
 public class AdminSchedulerAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-scheduler";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -67,11 +70,13 @@ public class AdminSchedulerAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             schedulerPager.setCurrentPageNumber(pageNumber.get());
@@ -84,6 +89,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, schedulerPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminScheduler_AdminSchedulerJsp).renderWith(data -> {
@@ -92,6 +98,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         schedulerPager.clear();
         return asHtml(path_AdminScheduler_AdminSchedulerJsp).renderWith(data -> {
@@ -114,6 +121,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     //                                            ----------
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnewjob(final String type, final String id, final String name) {
         saveToken();
         return asHtml(path_AdminScheduler_AdminSchedulerEditJsp).useForm(CreateForm.class, op -> {
@@ -140,6 +148,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminScheduler_AdminSchedulerEditJsp).useForm(CreateForm.class, op -> {
@@ -151,6 +160,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -174,6 +184,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -199,6 +210,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -219,6 +231,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -239,6 +252,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         final String id = form.id;
@@ -263,6 +277,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse start(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         final String id = form.id;
@@ -291,6 +306,7 @@ public class AdminSchedulerAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse stop(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         final String id = form.id;
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java
index 9e12a917bf549e400fb4dcd3fe50215acaed816f..4e0a4136f854093c21f5d07551643be6f2d8acfe 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java
@@ -29,6 +29,7 @@ import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.net.URLUtil;
 import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.entity.SearchRenderData;
 import org.codelibs.fess.es.client.FessEsClient;
@@ -56,6 +57,8 @@ import org.lastaflute.web.validation.VaMessenger;
  */
 public class AdminSearchlistAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-searchlist";
+
     // ===================================================================================
     // Constant
     //
@@ -113,6 +116,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     // Search Execute
     // ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final ListForm form) {
         saveToken();
         validate(form, messages -> {}, () -> asHtml(path_AdminError_AdminErrorJsp));
@@ -151,24 +155,28 @@ public class AdminSearchlistAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final ListForm form) {
         saveToken();
         return doSearch(form);
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse prev(final ListForm form) {
         saveToken();
         return doMove(form, -1);
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse next(final ListForm form) {
         saveToken();
         return doMove(form, 1);
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse move(final ListForm form) {
         saveToken();
         return doMove(form, 0);
@@ -192,6 +200,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     // -------
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final DeleteForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         verifyToken(() -> asListHtml());
@@ -207,6 +216,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse deleteall(final ListForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         verifyToken(() -> asListHtml());
@@ -223,6 +233,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew(final CreateForm form) {
         saveToken();
         form.initialize();
@@ -234,6 +245,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         getDoc(form).ifPresent(entity -> {
@@ -249,6 +261,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -277,6 +290,7 @@ public class AdminSearchlistAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/searchlog/AdminSearchlogAction.java b/src/main/java/org/codelibs/fess/app/web/admin/searchlog/AdminSearchlogAction.java
index 6b2217ac3775895ace64f45786dea21bbea52e64..2af15ea1274a497bb3d971a02e41623714247072 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/searchlog/AdminSearchlogAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/searchlog/AdminSearchlogAction.java
@@ -21,6 +21,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.pager.SearchLogPager;
 import org.codelibs.fess.app.service.SearchLogService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.util.RenderDataUtil;
 import org.lastaflute.web.Execute;
@@ -33,6 +34,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminSearchlogAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-searchlog";
+
     private static final String[] CONDITION_FIELDS =
             new String[] { "logType", "queryId", "userSessionId", "requestedTimeRange", "pageSize" };
 
@@ -57,12 +60,14 @@ public class AdminSearchlogAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final Integer pageNumber, final SearchForm form) {
         saveToken();
         searchLogPager.setCurrentPageNumber(pageNumber);
@@ -72,6 +77,7 @@ public class AdminSearchlogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         saveToken();
         searchLogPager.clear();
@@ -83,6 +89,7 @@ public class AdminSearchlogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         saveToken();
         searchLogPager.clear();
@@ -92,6 +99,7 @@ public class AdminSearchlogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse back(final SearchForm form) {
         saveToken();
         return asHtml(path_AdminSearchlog_AdminSearchlogJsp).renderWith(data -> {
@@ -114,6 +122,7 @@ public class AdminSearchlogAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String logType, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -132,6 +141,7 @@ public class AdminSearchlogAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
@@ -144,6 +154,7 @@ public class AdminSearchlogAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse deleteall() {
         verifyToken(this::asListHtml);
         searchLogPager.clear();
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/storage/AdminStorageAction.java b/src/main/java/org/codelibs/fess/app/web/admin/storage/AdminStorageAction.java
index 9b3da0a87a4171339a2722c02799591157d8c0b7..37afbe518c17832ad96f7c277386dd14cf97d9d4 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/storage/AdminStorageAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/storage/AdminStorageAction.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.codelibs.core.lang.StringUtil;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.crawler.Constants;
 import org.codelibs.fess.exception.StorageException;
@@ -51,6 +52,8 @@ import io.minio.messages.Item;
  */
 public class AdminStorageAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-storage";
+
     private static final Logger logger = LogManager.getLogger(AdminStorageAction.class);
 
     @Override
@@ -60,17 +63,14 @@ public class AdminStorageAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asListHtml(StringUtil.EMPTY);
     }
 
-    // TODO
-    //    @Execute
-    //    public HtmlResponse create() {
-    //    }
-
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse list(final OptionalThing<String> id) {
         saveToken();
         if (id.isPresent() && id.get() != null) {
@@ -80,6 +80,7 @@ public class AdminStorageAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upload(final ItemForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.path));
         if (form.uploadFile == null) {
@@ -101,6 +102,7 @@ public class AdminStorageAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public ActionResponse download(final String id) {
         final String[] values = decodeId(id);
         if (StringUtil.isEmpty(values[1])) {
@@ -121,6 +123,7 @@ public class AdminStorageAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final String id) {
         final String[] values = decodeId(id);
         if (StringUtil.isEmpty(values[1])) {
@@ -138,6 +141,7 @@ public class AdminStorageAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createDir(final ItemForm form) {
         validate(form, messages -> {}, () -> asListHtml(form.path));
         if (StringUtil.isBlank(form.name)) {
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/suggest/AdminSuggestAction.java b/src/main/java/org/codelibs/fess/app/web/admin/suggest/AdminSuggestAction.java
index 5368e39839e8b0a16f1917ff81da045adf7c527a..86431108d9906763a3c56316486531763efc939d 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/suggest/AdminSuggestAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/suggest/AdminSuggestAction.java
@@ -17,6 +17,7 @@ package org.codelibs.fess.app.web.admin.suggest;
 
 import javax.annotation.Resource;
 
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.helper.SuggestHelper;
 import org.lastaflute.web.Execute;
@@ -28,6 +29,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminSuggestAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-suggest";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -50,12 +53,14 @@ public class AdminSuggestAction extends FessAdminAction {
     //                                                                             Execute
     //                                                                            ========
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asHtml(path_AdminSuggest_AdminSuggestJsp).useForm(SuggestForm.class);
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse deleteAllWords() {
         if (!suggestHelper.deleteAllWords()) {
             throwValidationError(messages -> messages.addErrorsFailedToDeleteDocInAdmin(GLOBAL),
@@ -67,6 +72,7 @@ public class AdminSuggestAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse deleteDocumentWords() {
         if (!suggestHelper.deleteDocumentWords()) {
             throwValidationError(messages -> messages.addErrorsFailedToDeleteDocInAdmin(GLOBAL),
@@ -78,6 +84,7 @@ public class AdminSuggestAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse deleteQueryWords() {
         if (!suggestHelper.deleteQueryWords()) {
             throwValidationError(messages -> messages.addErrorsFailedToDeleteDocInAdmin(GLOBAL),
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/systeminfo/AdminSysteminfoAction.java b/src/main/java/org/codelibs/fess/app/web/admin/systeminfo/AdminSysteminfoAction.java
index cc9487e53037b61d43d58cb70993f95863e144b0..ad6dc59fee525a8faa0556101cf6584c881af8b8 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/systeminfo/AdminSysteminfoAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/systeminfo/AdminSysteminfoAction.java
@@ -25,6 +25,7 @@ import javax.annotation.Resource;
 import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.DynamicProperties;
 import org.codelibs.fess.Constants;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.mylasta.direction.FessConfig;
 import org.codelibs.fess.util.ComponentUtil;
@@ -40,6 +41,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminSysteminfoAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-systeminfo";
+
     private static final String MASKED_VALUE = "XXXXXXXX";
 
     // ===================================================================================
@@ -65,6 +68,7 @@ public class AdminSysteminfoAction extends FessAdminAction {
     //                                                                              Index
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asHtml(path_AdminSysteminfo_AdminSysteminfoJsp).renderWith(data -> {
             registerEnvItems(data);
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/upgrade/AdminUpgradeAction.java b/src/main/java/org/codelibs/fess/app/web/admin/upgrade/AdminUpgradeAction.java
index bc6644dc2869fc8544494203f018be47fdd0cf5e..572b1415913a2319dc5623fd261974abbc2188ba 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/upgrade/AdminUpgradeAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/upgrade/AdminUpgradeAction.java
@@ -20,6 +20,7 @@ import javax.annotation.Resource;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.codelibs.fess.app.service.ScheduledJobService;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.client.FessEsClient;
 import org.codelibs.fess.es.config.exbhv.DataConfigBhv;
@@ -38,6 +39,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
 
 public class AdminUpgradeAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-upgrade";
+
     // ===================================================================================
     //                                                                            Constant
     //
@@ -113,6 +116,7 @@ public class AdminUpgradeAction extends FessAdminAction {
     //                                                                      ==============
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         saveToken();
         return asIndexHtml();
@@ -123,6 +127,7 @@ public class AdminUpgradeAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse upgradeFrom(final UpgradeForm form) {
         validate(form, messages -> {}, this::asIndexHtml);
         verifyToken(this::asIndexHtml);
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/user/AdminUserAction.java b/src/main/java/org/codelibs/fess/app/web/admin/user/AdminUserAction.java
index b890d2cdfd93d568281db71aa4eb78db7b235eea..47b0dadae3f56a1d7a7465916e6d057d842b59b3 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/user/AdminUserAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/user/AdminUserAction.java
@@ -31,6 +31,7 @@ import org.codelibs.fess.app.service.GroupService;
 import org.codelibs.fess.app.service.RoleService;
 import org.codelibs.fess.app.service.UserService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.base.login.FessLoginAssist;
 import org.codelibs.fess.es.user.exentity.User;
@@ -50,6 +51,8 @@ import org.lastaflute.web.validation.VaErrorHook;
  */
 public class AdminUserAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-user";
+
     private static final Logger logger = LogManager.getLogger(AdminUserAction.class);
 
     // ===================================================================================
@@ -78,11 +81,13 @@ public class AdminUserAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             userPager.setCurrentPageNumber(pageNumber.get());
@@ -95,6 +100,7 @@ public class AdminUserAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, userPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminUser_AdminUserJsp).renderWith(data -> {
@@ -103,6 +109,7 @@ public class AdminUserAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         userPager.clear();
         return asHtml(path_AdminUser_AdminUserJsp).renderWith(data -> {
@@ -128,6 +135,7 @@ public class AdminUserAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminUser_AdminUserEditJsp).useForm(CreateForm.class, op -> {
@@ -141,6 +149,7 @@ public class AdminUserAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -165,6 +174,7 @@ public class AdminUserAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -189,6 +199,7 @@ public class AdminUserAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -211,6 +222,7 @@ public class AdminUserAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -233,6 +245,7 @@ public class AdminUserAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/webauth/AdminWebauthAction.java b/src/main/java/org/codelibs/fess/app/web/admin/webauth/AdminWebauthAction.java
index cd3b92eff6fc23f2c0ff838e990f22d92a2cbffd..ec5d50b036e5b0934a63a8dc9a5a8e3b8d84ca2d 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/webauth/AdminWebauthAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/webauth/AdminWebauthAction.java
@@ -28,6 +28,7 @@ import org.codelibs.fess.app.pager.WebAuthPager;
 import org.codelibs.fess.app.service.WebAuthenticationService;
 import org.codelibs.fess.app.service.WebConfigService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.WebAuthentication;
 import org.codelibs.fess.es.config.exentity.WebConfig;
@@ -47,6 +48,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminWebauthAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-webauth";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -70,11 +73,13 @@ public class AdminWebauthAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             webAuthPager.setCurrentPageNumber(pageNumber.get());
@@ -87,6 +92,7 @@ public class AdminWebauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, webAuthPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminWebauth_AdminWebauthJsp).renderWith(data -> {
@@ -95,6 +101,7 @@ public class AdminWebauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         webAuthPager.clear();
         return asHtml(path_AdminWebauth_AdminWebauthJsp).renderWith(data -> {
@@ -116,6 +123,7 @@ public class AdminWebauthAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asHtml(path_AdminWebauth_AdminWebauthEditJsp).useForm(CreateForm.class, op -> {
@@ -130,6 +138,7 @@ public class AdminWebauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -153,6 +162,7 @@ public class AdminWebauthAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -177,6 +187,7 @@ public class AdminWebauthAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -197,6 +208,7 @@ public class AdminWebauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -217,6 +229,7 @@ public class AdminWebauthAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/webconfig/AdminWebconfigAction.java b/src/main/java/org/codelibs/fess/app/web/admin/webconfig/AdminWebconfigAction.java
index c0340c87d7115d8e362166a5d5d9d3f822e17d83..3421093642154da3065b9f813305285021d844dd 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/webconfig/AdminWebconfigAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/webconfig/AdminWebconfigAction.java
@@ -31,6 +31,7 @@ import org.codelibs.fess.app.service.RoleTypeService;
 import org.codelibs.fess.app.service.ScheduledJobService;
 import org.codelibs.fess.app.service.WebConfigService;
 import org.codelibs.fess.app.web.CrudMode;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.config.exentity.WebConfig;
 import org.codelibs.fess.helper.PermissionHelper;
@@ -51,6 +52,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
  */
 public class AdminWebconfigAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-webconfig";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -78,11 +81,13 @@ public class AdminWebconfigAction extends FessAdminAction {
     //                                                                      Search Execute
     //                                                                      ==============
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index(final SearchForm form) {
         return asListHtml();
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse list(final OptionalThing<Integer> pageNumber, final SearchForm form) {
         pageNumber.ifPresent(num -> {
             webConfigPager.setCurrentPageNumber(pageNumber.get());
@@ -95,6 +100,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse search(final SearchForm form) {
         copyBeanToBean(form, webConfigPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
         return asHtml(path_AdminWebconfig_AdminWebconfigJsp).renderWith(data -> {
@@ -103,6 +109,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse reset(final SearchForm form) {
         webConfigPager.clear();
         return asHtml(path_AdminWebconfig_AdminWebconfigJsp).renderWith(data -> {
@@ -124,6 +131,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     //                                            Entry Page
     //                                            ----------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse createnew() {
         saveToken();
         return asEditHtml().useForm(CreateForm.class, op -> {
@@ -135,6 +143,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse edit(final EditForm form) {
         validate(form, messages -> {}, () -> asListHtml());
         final String id = form.id;
@@ -173,6 +182,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     //                                               Details
     //                                               -------
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse details(final int crudMode, final String id) {
         verifyCrudMode(crudMode, CrudMode.DETAILS);
         saveToken();
@@ -212,6 +222,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     //                                         Actually Crud
     //                                         -------------
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -232,6 +243,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, () -> asEditHtml());
@@ -252,6 +264,7 @@ public class AdminWebconfigAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse delete(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.DETAILS);
         validate(form, messages -> {}, () -> asDetailsHtml());
diff --git a/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java b/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java
index c61897b501e562b6836e2800d6b7831f42f8fd2a..9ac2eac535688d41ecb8977661c70286f5dd4347 100644
--- a/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java
@@ -30,6 +30,7 @@ import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.service.FileConfigService;
 import org.codelibs.fess.app.service.ScheduledJobService;
 import org.codelibs.fess.app.service.WebConfigService;
+import org.codelibs.fess.app.web.annotation.Secured;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.crawler.util.CharUtil;
 import org.codelibs.fess.es.config.exentity.FileConfig;
@@ -45,6 +46,8 @@ import org.lastaflute.web.ruts.process.ActionRuntime;
 
 public class AdminWizardAction extends FessAdminAction {
 
+    public static final String ROLE = "admin-wizard";
+
     // ===================================================================================
     //                                                                            Constant
     //
@@ -82,6 +85,7 @@ public class AdminWizardAction extends FessAdminAction {
     //                                                                      ==============
 
     @Execute
+    @Secured({ ROLE, ROLE + VIEW })
     public HtmlResponse index() {
         return asIndexHtml();
     }
@@ -91,12 +95,14 @@ public class AdminWizardAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse crawlingConfigForm() {
         saveToken();
         return asHtml(path_AdminWizard_AdminWizardConfigJsp).useForm(CrawlingConfigForm.class);
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse crawlingConfig(final CrawlingConfigForm form) {
         validate(form, messages -> {}, () -> {
             return asHtml(path_AdminWizard_AdminWizardConfigJsp);
@@ -108,6 +114,7 @@ public class AdminWizardAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse crawlingConfigNext(final CrawlingConfigForm form) {
         validate(form, messages -> {}, () -> {
             return asHtml(path_AdminWizard_AdminWizardConfigJsp);
@@ -272,12 +279,14 @@ public class AdminWizardAction extends FessAdminAction {
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse startCrawlingForm() {
         saveToken();
         return asHtml(path_AdminWizard_AdminWizardStartJsp).useForm(StartCrawlingForm.class);
     }
 
     @Execute
+    @Secured({ ROLE })
     public HtmlResponse startCrawling(final StartCrawlingForm form) {
         verifyToken(() -> asIndexHtml());
         if (!processHelper.isProcessRunning()) {
diff --git a/src/main/java/org/codelibs/fess/app/web/annotation/Secured.java b/src/main/java/org/codelibs/fess/app/web/annotation/Secured.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e4e8c7e81b17e032c5a1283edcbafff8f364a78
--- /dev/null
+++ b/src/main/java/org/codelibs/fess/app/web/annotation/Secured.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-2019 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.app.web.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Java 5 annotation for describing service layer security attributes.
+ *
+ * <p>
+ * The <code>Secured</code> annotation is used to define a list of security configuration
+ * attributes for business methods. 
+ * <p>
+ * For example:
+ *
+ * <pre>
+ * &#064;Secured({ &quot;ROLE_USER&quot; })
+ * public void create(Contact contact);
+ *
+ * &#064;Secured({ &quot;ROLE_USER&quot;, &quot;ROLE_ADMIN&quot; })
+ * public void update(Contact contact);
+ *
+ * &#064;Secured({ &quot;ROLE_ADMIN&quot; })
+ * public void delete(Contact contact);
+ * </pre>
+ * @author Mark St.Godard
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+public @interface Secured {
+    /**
+     * Returns the list of security configuration attributes (e.g.&nbsp;ROLE_USER, ROLE_ADMIN).
+     *
+     * @return String[] The secure method attributes
+     */
+    String[] value();
+}
diff --git a/src/main/java/org/codelibs/fess/app/web/base/FessAdminAction.java b/src/main/java/org/codelibs/fess/app/web/base/FessAdminAction.java
index af482d3bfcc040e04da05fadf258568ea4ab0f35..dad0de61639b25e03d76665085417d0934655648 100644
--- a/src/main/java/org/codelibs/fess/app/web/base/FessAdminAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/base/FessAdminAction.java
@@ -33,6 +33,8 @@ import org.lastaflute.web.util.LaServletContextUtil;
  */
 public abstract class FessAdminAction extends FessBaseAction {
 
+    public static final String VIEW = "-view";
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
diff --git a/src/main/java/org/codelibs/fess/app/web/base/FessLoginAction.java b/src/main/java/org/codelibs/fess/app/web/base/FessLoginAction.java
index 6f7181f7476418761ee90cb7c4ba84254c4c5466..2c1427356c49e3a317e19c9d93aab7fcde414cb7 100644
--- a/src/main/java/org/codelibs/fess/app/web/base/FessLoginAction.java
+++ b/src/main/java/org/codelibs/fess/app/web/base/FessLoginAction.java
@@ -15,6 +15,7 @@
  */
 package org.codelibs.fess.app.web.base;
 
+import org.codelibs.fess.app.web.admin.AdminAction;
 import org.codelibs.fess.app.web.admin.dashboard.AdminDashboardAction;
 import org.codelibs.fess.mylasta.action.FessUserBean;
 import org.lastaflute.web.response.HtmlResponse;
@@ -25,9 +26,13 @@ public abstract class FessLoginAction extends FessSearchAction {
     }
 
     protected HtmlResponse redirectByUser(final FessUserBean user) {
-        if (!user.hasRoles(fessConfig.getAuthenticationAdminRolesAsArray())) {
-            return redirectToRoot();
+        if (user.hasRoles(fessConfig.getAuthenticationAdminRolesAsArray())) {
+            return redirect(AdminDashboardAction.class);
         }
-        return redirect(AdminDashboardAction.class);
+        final Class<? extends FessAdminAction> actionClass = AdminAction.getAdminActionClass(user);
+        if (actionClass != null) {
+            return redirect(actionClass);
+        }
+        return redirectToRoot();
     }
 }
diff --git a/src/main/java/org/codelibs/fess/app/web/base/login/FessLoginAssist.java b/src/main/java/org/codelibs/fess/app/web/base/login/FessLoginAssist.java
index 4c3622fd9c68fc2522af0a5d0f61ee852c696f82..bc6d7b0289da1776eb283f163bbb53f95531e136 100644
--- a/src/main/java/org/codelibs/fess/app/web/base/login/FessLoginAssist.java
+++ b/src/main/java/org/codelibs/fess/app/web/base/login/FessLoginAssist.java
@@ -15,12 +15,14 @@
  */
 package org.codelibs.fess.app.web.base.login;
 
+import java.lang.reflect.Method;
 import java.util.function.Function;
 
 import javax.annotation.Resource;
 
-import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.web.RootAction;
+import org.codelibs.fess.app.web.annotation.Secured;
+import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.app.web.login.LoginAction;
 import org.codelibs.fess.entity.FessUser;
 import org.codelibs.fess.es.user.exbhv.UserBhv;
@@ -110,11 +112,17 @@ public class FessLoginAssist extends TypicalLoginAssist<String, FessUserBean, Fe
 
     @Override
     protected void checkPermission(final LoginHandlingResource resource) throws LoginRequiredException {
-        if (resource.getActionClass().getName().startsWith(Constants.ADMIN_PACKAGE)) {
+        if (FessAdminAction.class.isAssignableFrom(resource.getActionClass())) {
             getSavedUserBean().ifPresent(user -> {
-                if (!user.hasRoles(fessConfig.getAuthenticationAdminRolesAsArray())) {
-                    throw new UserRoleLoginException(RootAction.class);
+                if (user.hasRoles(fessConfig.getAuthenticationAdminRolesAsArray())) {
+                    return;
                 }
+                final Method executeMethod = resource.getExecuteMethod();
+                final Secured secured = executeMethod.getAnnotation(Secured.class);
+                if (secured != null && user.hasRoles(secured.value())) {
+                    return;
+                }
+                throw new UserRoleLoginException(RootAction.class);
             });
         }
     }