首页 > 代码库 > Liferay7 BPM门户开发之32: 实现自定义认证登陆(定制Authentication Hook)
Liferay7 BPM门户开发之32: 实现自定义认证登陆(定制Authentication Hook)
优秀的平台必然松耦合、易扩展 -- 王昕
第一步:修改liferay-hook.xml
<?xml version="1.0"?><!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd"><hook><portal-properties>portal.properties</portal-properties></hook>
如果是liferay7则不需要这一步,只需要注解:
@Component(immediate = true, property = {"key=auth.pipeline.pre"},service = Authenticator.class)
第二步:配置认证属性portal.properties
auth.pipeline.pre=com.proliferay.YourAuthenticator
配置auth.pipeline.post 还将进行密码检查,liferay的内部机制是2级检查,一级是身份认证,二级是密码检查,实际上可以通过SKIP_LIFERAY_CHECK来统一处理
第三步:开发定制的认证类
import java.util.Map;import com.liferay.portal.security.auth.AuthException;import com.liferay.portal.security.auth.Authenticator; public class YourAuthenticator implements Authenticator { @Override public int authenticateByEmailAddress(long companyId, String emailAddress, String password, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { /** * 这里是认证的逻辑 */ return SKIP_LIFERAY_CHECK; } @Override public int authenticateByScreenName(long companyId, String screenName, String password, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { return DNE; } @Override public int authenticateByUserId(long companyId, long userId, String password, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { return DNE; } }
常数定义:
- public static final int DNE = 0; //用户不存在
- public static final int FAILURE = -1;//认证失败
- public static final int SKIP_LIFERAY_CHECK = 2;
- public static final int SUCCESS = 1;
要注意SKIP_LIFERAY_CHECK和SUCCESS的区别,通过SKIP_LIFERAY_CHECK来统一处理身份认证,跳过门户的密码检查,如果返回SUCCESS,则必须配合auth.pipeline.post来进行密码检查。
通过图来说明:
一个具体的例子:
集成Apache Shiro的认证登陆
import com.liferay.portal.kernel.log.Log;import com.liferay.portal.kernel.log.LogFactoryUtil;import com.liferay.portal.kernel.security.auth.AuthException;import com.liferay.portal.kernel.security.auth.Authenticator;import java.util.Map;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.osgi.service.component.annotations.Activate;import org.osgi.service.component.annotations.Component;@Component( immediate = true, property = {"key=auth.pipeline.pre"}, service = Authenticator.class)public class ShiroAuthenticatorPre implements Authenticator { @Activate public void activate() { Factory<SecurityManager> factory = new IniSecurityManagerFactory( "classpath:userauth.ini"); //shiro配置文件 SecurityUtils.setSecurityManager(factory.getInstance()); if (_log.isInfoEnabled()) { _log.info("activate"); } } @Override public int authenticateByEmailAddress( long companyId, String emailAddress, String password, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { if (_log.isInfoEnabled()) { _log.info("authenticateByEmailAddress"); } UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken( emailAddress, password); Subject currentUser = SecurityUtils.getSubject(); try { //shiro的代理登陆 currentUser.login(usernamePasswordToken); boolean authenticated = currentUser.isAuthenticated(); if (authenticated) { if (_log.isInfoEnabled()) { _log.info("authenticated"); } return SKIP_LIFERAY_CHECK; //认证通过 } else { return FAILURE; } } catch (AuthenticationException ae) { _log.error(ae.getMessage(), ae); throw new AuthException(ae.getMessage(), ae); } } @Override public int authenticateByScreenName( long companyId, String screenName, String password, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { if (_log.isInfoEnabled()) { _log.info("authenticateByScreenName - not implemented "); } return SUCCESS; } @Override public int authenticateByUserId( long companyId, long userId, String password, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { if (_log.isInfoEnabled()) { _log.info("authenticateByScreenName - not implemented "); } return SUCCESS; } private static final Log _log = LogFactoryUtil.getLog( ShiroAuthenticatorPre.class);}
apache shiro框架结构
apache shiro是一套非常著名的安全框架,提供了认证、授权、加密和会话管理功能
了解更多apache shiro的知识:http://www.infoq.com/cn/articles/apache-shiro
Authentication的Token令牌机制
了解更多Authentication Token:https://web.liferay.com/zh/community/wiki/-/wiki/Main/Authentication+Token
Token令牌是为了避免CSRF跨站伪造。
了解更多CSRF:https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
定义认证失败的扩展处理
import com.liferay.portal.kernel.exception.PortalException;import com.liferay.portal.kernel.log.Log;import com.liferay.portal.kernel.log.LogFactoryUtil;import com.liferay.portal.kernel.model.User;import com.liferay.portal.kernel.security.auth.AuthException;import com.liferay.portal.kernel.security.auth.AuthFailure;import com.liferay.portal.kernel.service.UserLocalServiceUtil;import java.util.Map;import org.osgi.service.component.annotations.Component;@Component( immediate = true, property = {"key=auth.failure"}, service = AuthFailure.class)public class LogAuthFailure implements AuthFailure { @Override public void onFailureByEmailAddress( long companyId, String emailAddress, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { try { User user = UserLocalServiceUtil.getUserByEmailAddress( companyId, emailAddress); int failures = user.getFailedLoginAttempts(); if (_log.isInfoEnabled()) { _log.info( "onFailureByEmailAddress: " + emailAddress + " has failed to login " + failures + " times"); } } catch (PortalException pe) { } } @Override public void onFailureByScreenName( long companyId, String screenName, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { try { User user = UserLocalServiceUtil.getUserByScreenName( companyId, screenName); int failures = user.getFailedLoginAttempts(); if (_log.isInfoEnabled()) { _log.info( "onFailureByScreenName: " + screenName + " has failed to login " + failures + " times"); } } catch (PortalException pe) { } } @Override public void onFailureByUserId( long companyId, long userId, Map<String, String[]> headerMap, Map<String, String[]> parameterMap) throws AuthException { try { User user = UserLocalServiceUtil.getUserById(userId); int failures = user.getFailedLoginAttempts(); if (_log.isInfoEnabled()) { _log.info( "onFailureByUserId: userId " + userId + " has failed to login " + failures + " times"); } } catch (PortalException pe) { } } private static final Log _log = LogFactoryUtil.getLog(LogAuthFailure.class);}
Liferay7 BPM门户开发之32: 实现自定义认证登陆(定制Authentication Hook)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。