【JBoss】3. JBoss SX安全框架
来源:互联网 发布:网络兼职论坛发帖 编辑:程序博客网 时间:2024/06/05 20:39
JBoss SX
JBoss使用JBoss SX框架来确保应用程序安全。它建立在Java身份验证和授权服务的顶层(JAAS,Java Authentication and Authorization Service)。
当JBoss接收到请求时,目标应用程序不需要知道基本安全数据库的位置或访问方式;
请求被传递到名为“安全域”的JBoss SX组件中,这是一种用来保护所有对组件的球球的抽象;
安全域执行所有必要的安全检查并告知组件用户可否继续进行访问,安全域知道如何使用一个或多个登录模块从数据源加载安全数据;
安全域
可以在server/x/conf/login-config.xml中添加或更改现有安全域定义。
<application-policy>定义一个安全域,JBoss SX根据name生成JNDI上下文,并使用该上下文将安全域绑定到JNDI中;
<login-module>定义登录模块,登录模块可以从属性文件、或数据库中加载安全信息(密码、角色)。
<!--application-policy:定义安全域--><application-policy name="authnservice"> <authentication> <!--login-module:定义登录模块--> <login-module code="com.alpha.security.authentication.TokenLoginModule" flag="required"/> <login-module code="com.alpha.security.authentication.LockedAccountLoginModule" flag="required"> <module-option name="dsJndiName">java:/OracleDS</module-option> <module-option name="lockingQuery"> SELECT 。。。 </module-option> <module-option name="updateLocked"> UPDATE USER 。。。 </module-option> <module-option name="updateFailLoginCount"> UPDATE USER 。。。 </module-option> </login-module> <login-module code="com.alpha.security.authentication.TokenServiceLoginModule" flag="required"> <module-option name="unauthenticatedIdentity">guest</module-option> <module-option name="dsJndiName">java:/OracleDS</module-option> <module-option name="hashAlgorithm">SHA-1</module-option> <module-option name="hashEncoding">hex</module-option> <module-option name="principalsQuery"> select PASSWORDfrom 。。。 </module-option> <module-option name="rolesQuery"> SELECT Roles FROM ROLE r,。。。 </module-option> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="rolePrefix">alpha/</module-option> <module-option name="hashCharset">UTF-8</module-option> </login-module> <login-module code="com.alpha.security.authentication.PasswordExpirationLoginModule" flag="required"> <module-option name="dsJndiName">java:/OracleDS</module-option> <module-option name="passwordQuery"> select date_of_creation, date_of_expiration from (select pw.* from sec_password pw, sec_user uwhere u.login_name = UPPER(?) and pw.user_id = u.id order by pw.date_of_creation desc) where rownum=1 </module-option> <module-option name="checkEnabledQuery"> select v.boolean_value from config_key k, config_value v where k.key = 'Options.system.settings.pwExpireEnabled'and v.key = k.id </module-option> <module-option name="checkFirstLoginQuery"> select v.boolean_value from config_key k, config_value v where k.key = 'Options.system.settings.enableFirstLogin'and v.key = k.id </module-option> <module-option name="passAgeQuery"> select v.integer_value from config_key k, config_value v where k.key = 'Options.system.settings.pwExpireAge'and v.key = k.id </module-option> <module-option name="notifyPeriodQuery"> select v.integer_value from config_key k, config_value v where k.key = 'Options.system.settings.pwNotifyPeriod'and v.key = k.id </module-option> </login-module> <login-module code="com.alpha.security.authentication.RoleMappingLoginModule" flag="required"> <module-option name="mapping"> 。。。 </module-option> </login-module> <login-module code="com.alpha.security.authentication.TokenCreatingLoginModule" flag="required"/></authentication></application-policy>
JMX查看安全域
jboss.security - service=XMLLoginConfig
displayAppConfig( "authnservice" )
安全域信息:
登录模块UsersRolesLoginModule
登录模块可以从属性文件、或数据库中加载安全信息(密码、角色)。
前面的例子中,登录模块是自定义的。
JBoss SX提供了多个登录模块,其中UsersRolesLoginModule用于在属性文件中存储用户名和角色信息。
<application-policy name="JBossWS"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="usersProperties">props/jbossws-users.properties</module-option> <module-option name="rolesProperties">props/jbossws-roles.properties</module-option> <module-option name="unauthenticatedIdentity">anonymous</module-option> </login-module> </authentication> </application-policy>
这种登录模块常用于开发和测试。
登录模块DatabaseServerLoginModule
DatabaseServerLoginModule用于在数据库中存储用户名和角色信息:
<login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="dsJndiName">java:/pacsDS</module-option> <module-option name="principalsQuery">select passwd from users where user_id=?</module-option> <module-option name="rolesQuery">select roles from roles where user_id=?</module-option> <module-option name="hashEncoding">base64</module-option> <module-option name="hashCharset">UTF-8</module-option> <module-option name="hashAlgorithm">SHA-1</module-option></login-module><dsJndiName>定义了数据源的JNDI名称。
自定义登录模块
继承javax.security.auth.spi.LoginModule:
import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Timestamp;import java.util.Map;import javax.security.auth.Subject;import javax.security.auth.callback.CallbackHandler;import javax.security.auth.login.AccountExpiredException;import javax.security.auth.login.LoginException;import javax.security.auth.spi.LoginModule;import org.apache.log4j.Logger;import org.jboss.security.SecurityContextAssociation;public class PasswordExpirationLoginModule implements LoginModule {private static final Logger log = Logger.getLogger(PasswordExpirationLoginModule.class);private final class PasswordDao extends LoginModuleDAO {private final String userName;Timestamp expireDate;Timestamp createDate;private PasswordDao(String userName) {super(dsJndiName);this.userName = userName;}@Overridepublic void innerRun(Connection conn, PreparedStatement ps, ResultSet rs) throws SQLException,LoginException {ps = conn.prepareStatement(passwordQuery);ps.setString(1, userName);rs = ps.executeQuery();if (rs.next()) {expireDate = rs.getTimestamp("date_of_expiration");createDate = rs.getTimestamp("date_of_creation");}}}private final class SettingDAO<T> extends LoginModuleDAO {private final String query;private T data;private final Class<T> type;private SettingDAO(String query, Class<T> type) {super(dsJndiName);this.query = query;this.type = type;}@Overridepublic void innerRun(Connection conn, PreparedStatement ps, ResultSet rs) throws SQLException,LoginException {ps = conn.prepareStatement(query);rs = ps.executeQuery();if (rs.next()) {if(type==Integer.class) {data = (T) Integer.valueOf(rs.getInt(1));}else if(type==Boolean.class) {data = (T) Boolean.valueOf(rs.getBoolean(1));}else if(type==Timestamp.class) {data = (T) rs.getTimestamp(1);}else {data = (T) rs.getObject(1);}}}public T getResult() {return data;}}/** * Flag to allow ignore "about to expire" checking */public static final String IGNORE_EXPIRED = "ignore_expired";//mili seconds in a dayprivate static final long timeADay = 86400000L;private String dsJndiName;//get pw creation date and expiration dateprivate String passwordQuery;private String checkEnabledQuery;private String checkFirstLoginQuery;private String notifyPeriodQuery;private String passAgeQuery;private CallbackHandler callbackHandler;private CallbackHelper helper = new CallbackHelper(); @Overridepublic void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState,Map options) {this.callbackHandler = callbackHandler;dsJndiName = (String) options.get("dsJndiName");passwordQuery = (String) options.get("passwordQuery");checkEnabledQuery = (String) options.get("checkEnabledQuery");checkFirstLoginQuery = (String) options.get("checkFirstLoginQuery");notifyPeriodQuery = (String) options.get("notifyPeriodQuery");passAgeQuery = (String) options.get("passAgeQuery");} @Overridepublic boolean login() throws LoginException {if(log.isDebugEnabled()) {log.debug("do expire check");}final String userName = helper.getUsername(callbackHandler);PasswordDao dao = new PasswordDao(userName);dao.run();if(isCheckFirstLoginEnabled()) {if(dao.expireDate!=null && dao.expireDate.equals(dao.createDate)) {throw new FirstLoginException();}}if(isCheckEnabled()) {long passAge = getPassAge() * timeADay;SettingDAO<Timestamp> timeDao = new SettingDAO<Timestamp>("select systimestamp from dual", Timestamp.class);timeDao.run();Timestamp now = timeDao.getResult();if(dao.expireDate!=null) {log.warn("expiration date has been set for current password.");long time = dao.expireDate.getTime() - dao.createDate.getTime();if(time>0) {passAge = Math.min(passAge, time);}}long currentAge = now.getTime() - dao.createDate.getTime();if(currentAge >= passAge) {throw new AccountExpiredException();}//ignore about to expireBoolean isIgnore = (Boolean)(SecurityContextAssociation .getSecurityContext().getData().get(IGNORE_EXPIRED));if(isIgnore!=null && isIgnore) {return false;}long notifiPeriod = getNotifyPeriod() * timeADay;if(currentAge >= passAge - notifiPeriod) {long time = passAge -currentAge;int day = (int)(time / timeADay + (time % timeADay==0 ? 0 : 1));throw new AccountToExpireException(day);}}return false;}private boolean isCheckFirstLoginEnabled() throws LoginException {SettingDAO<Boolean> dao = new SettingDAO(checkFirstLoginQuery, Boolean.class);dao.run();Boolean result = dao.getResult();return result;}private int getNotifyPeriod() throws LoginException{SettingDAO<Integer> dao = new SettingDAO(notifyPeriodQuery, Integer.class);dao.run();Integer data = dao.getResult();if(data==null) {log.warn("setting for notify period is not found, use hardcode value 14");return 14;}return data;}private int getPassAge() throws LoginException {SettingDAO<Integer> dao = new SettingDAO(passAgeQuery, Integer.class);dao.run();Integer data = dao.getResult();if(data==null) {log.warn("setting for password expired age is not found");return 42;}return data;}private boolean isCheckEnabled() throws LoginException{SettingDAO<Boolean> dao = new SettingDAO(checkEnabledQuery, Boolean.class);dao.run();Boolean result = dao.getResult();return result;} @Overridepublic boolean commit() throws LoginException {return false;} @Overridepublic boolean abort() throws LoginException {return false;} @Overridepublic boolean logout() throws LoginException {return false;}}
- 【JBoss】3. JBoss SX安全框架
- JBOSS安全
- jboss
- JBOSS
- JBoss
- jboss
- jboss
- Jboss
- JBoss
- JBOSS
- JBoss
- Jboss
- Jboss
- jboss
- JBOSS
- jboss
- Jboss
- jboss
- WinForm(C#)CheckedlistBox绑定数据,并获得选中的值(ValueMember)和显示文本(DisplayMember
- HOJ 1031 Piggy-Bank
- 在SQLServer2005中使用SQL语句插入数据出现乱码或问号的解决方法
- 数组地址问题,实验结果~
- (五)struts1之OGNL使用
- 【JBoss】3. JBoss SX安全框架
- Java学习笔记之final 关键字和抽象类
- access实现limit分页
- 在Struts2中使用ValueStack、ActionContext、ServletContext、request、session等 .
- QT学习(四)----360界面制作(1)
- java中操作Date
- node.js解析xml(xmlreader)
- C/C++中Sqlite使用简介
- Debug手机出现Android Unable to open sync connection!