Liferay基于角色的登录重定向实现及空指针问题排查
问题解决:Liferay登录Hook角色跳转与空指针修复
空指针异常原因分析
你的代码出现NPE有两个核心原因:
RoleLocalService未注入:Liferay的OSGi组件需要通过@Reference注解注入服务,直接使用未初始化的roleLocalService会导致空指针;- 未处理
fetchRole返回null的情况:如果角色名称不存在(比如大小写错误),fetchRole会返回null,此时调用getRoleId()会触发NPE。
修改后的完整代码
@Component( immediate = true, property = {"key=login.events.post"}, service = LifecycleAction.class ) public class MyCustomLoginHookLoginPostAction extends Action { private final static String PUBLIC_PAGE_CONTEXT = "/web"; private final static String PRIVATE_PAGE_CONTEXT = "/group"; // 站点1的友好URL,根据实际情况修改 private final static String SITE1_FRIENDLY_URL = "/site1"; // 管理员页面和经理页面的路径,根据实际页面友好URL修改 private final static String ADMIN_PAGE_PATH = "/admin-dashboard"; private final static String MANAGER_PAGE_PATH = "/manager-workspace"; @Reference private RoleLocalService roleLocalService; @Override public void run(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ActionException { final long companyId = PortalUtil.getCompanyId(httpServletRequest); String path = PrefsPropsUtil.getString(companyId, PropsKeys.DEFAULT_LANDING_PAGE_PATH); try { path = getCustomLandingPage(httpServletRequest); } catch (PortalException e) { throw new ActionException(e); } if (Validator.isNotNull(path)) { final HttpSession httpSession = httpServletRequest.getSession(); httpSession.setAttribute(WebKeys.LAST_PATH, new LastPath(StringPool.BLANK, path)); } } private String getCustomLandingPage(HttpServletRequest httpServletRequest) throws PortalException { String path = null; final long companyId = PortalUtil.getCompanyId(httpServletRequest); User user = PortalUtil.getUser(httpServletRequest); // 1. 优先处理角色对应的跳转逻辑 // 获取Administrator角色,注意角色名称是Liferay内置的,大小写敏感 Role roleAdministrator = roleLocalService.fetchRole(companyId, "Administrator"); if (roleAdministrator != null && roleLocalService.hasUserRole(user.getUserId(), roleAdministrator.getRoleId())) { // 跳转至站点1的管理员页面 path = PUBLIC_PAGE_CONTEXT + SITE1_FRIENDLY_URL + ADMIN_PAGE_PATH; return path; } // 获取Manager角色 Role roleManager = roleLocalService.fetchRole(companyId, "Manager"); if (roleManager != null && roleLocalService.hasUserRole(user.getUserId(), roleManager.getRoleId())) { // 跳转至站点1的经理页面 path = PUBLIC_PAGE_CONTEXT + SITE1_FRIENDLY_URL + MANAGER_PAGE_PATH; return path; } // 2. 原有站点跳转逻辑 List<Organization> orgs = user.getOrganizations(); if (orgs != null && !orgs.isEmpty()) { for (Organization org : orgs) { Group orgSite = org.getGroup(); if (orgSite == null) continue; // 增加空判断,避免后续NPE int publicPageCount = orgSite.getPublicLayoutsPageCount(); int privatePageCount = orgSite.getPrivateLayoutsPageCount(); if (publicPageCount > 0) { path = PUBLIC_PAGE_CONTEXT + orgSite.getFriendlyURL(); break; } else if (privatePageCount > 0) { path = PRIVATE_PAGE_CONTEXT + orgSite.getFriendlyURL(); break; } } } if (Validator.isNull(path)) { List<Group> sites = user.getGroups(); if (sites != null && !sites.isEmpty()) { for (Group site : sites) { if (site == null) continue; // 增加空判断 int publicPageCount = site.getPublicLayoutsPageCount(); int privatePageCount = site.getPrivateLayoutsPageCount(); if (publicPageCount > 0) { path = PUBLIC_PAGE_CONTEXT + site.getFriendlyURL(); break; } else if (privatePageCount > 0) { path = PRIVATE_PAGE_CONTEXT + site.getFriendlyURL(); break; } } } } if (Validator.isNull(path)) { path = PrefsPropsUtil.getString(companyId, PropsKeys.DEFAULT_LANDING_PAGE_PATH); } return path; } }
关键修改点说明
- 注入
RoleLocalService:通过@Reference注解让Liferay的OSGi容器自动注入服务实例,解决roleLocalService为null的问题; - 角色校验的空安全处理:每次调用
fetchRole后先判断角色是否为null,再调用hasUserRole和getRoleId(); - 优先角色跳转逻辑:将角色判断放在原有站点逻辑之前,确保管理员/经理用户优先跳转到指定页面;
- 增加Group空判断:在原有逻辑中增加
orgSite == null和site == null的判断,避免潜在的空指针; - 配置页面路径常量:将站点和页面路径定义为常量,方便后续修改维护,注意要根据你实际的站点友好URL和页面路径调整这些值。
额外注意事项
- 角色名称是大小写敏感的,Liferay内置的
Administrator和Manager角色名称必须完全匹配; - 如果管理员/经理页面是私有页面,需要将
PUBLIC_PAGE_CONTEXT替换为PRIVATE_PAGE_CONTEXT; - 测试时确保用户确实拥有对应的角色,并且页面路径正确存在。
内容的提问来源于stack exchange,提问作者SnIpEr ReLoAdEd
相关产品推荐
相关产品推荐

