2015年9月30日星期三

EAP_035:EAP 功能演示 5:数据库认证

环境:JBoss EAP 6.4.0

1.  配置derby 数据源
请参考《EAP 6 功能演示2 :DataSource 部署》。


2. 创建数据库表
这里使用之前已经创建好的 derby:demoDB
(1)cd /Users/maping/Apache/db-derby/bin
        进入SQL交互 ./ij
    ij> Connect 'jdbc:derby:demoDB;user=demo;password=demo';
    ij> CREATE TABLE principles ( principal_id VARCHAR(64) primary key,password VARCHAR(64));
    ij> CREATE TABLE roles ( principal_id VARCHAR(64),user_role VARCHAR(64),role_group VARCHAR(64));
    ij>INSERT INTO principles VALUES('TestUserOne','PasswordOne');
    ij>INSERT INTO principles VALUES('TestUserTwo','PasswordTwo');
    ij>INSERT INTO roles VALUES('TestUserOne','TestRoleOne','TestUserOneGroup');
    ij>INSERT INTO roles VALUES('TestUserTwo','TestRoleTwo','TestUserTwoGroup');
(2)cd /Users/maping/Apache/db-derby/bin
    启动 ./startNetworkServer
    停止 ./stopNetworkServer

3. 修改 EAP 配置文件
(1)cp standalone.xml standalone-database-auth.xml
(2)vim standalone-database-auth.xml
<security-domain name="DBAuthTest" cache-type="default">
                    <authentication>
                        <login-module code="Database" flag="required">
                            <module-option name="dsJndiName" value="java:jboss/datasources/DemoDataSource"/>
                            <module-option name="principalsQuery" value="select password from  PRINCIPLES where principal_id=?"/>
                            <module-option name="rolesQuery" value="select user_role, 'Roles' from  ROLES where  principal_id=?"/>
                        </login-module>
                    </authentication>
                </security-domain>

如果有必要,可以输出详细的安全日志,用于调试
<category name="org.jboss.security">
   <priority value="TRACE"/>
</category>

4. 修改Web应用配置文件
(1)web.xml
    <security-constraint>
        <display-name>Constraint-0</display-name>
        <web-resource-collection>
            <web-resource-name>Constraint-0</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>*</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
   
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/jsp/login.jsp</form-login-page>
            <form-error-page>/jsp/login-error.jsp</form-error-page>
        </form-login-config>
    </login-config>
   
    <security-role>
        <role-name>TestRoleOne</role-name>
    </security-role>

(2)jboss-web.xml
    <security-domain>java:/jaas/DBAuthTest</security-domain>

5. 部署example_auth.war

6. 访问:http://localhost:18080/example_auth/
需要登录,输入用户:TestUserOne 口令:PasswordOne。

参考文献:
1. http://middlewaremagic.com/jboss/?p=387

EAP_034:EAP 6 功能演示 4:JMS

环境:JBoss  EAP 6.4

1. 概念与术语
(1)HornetQ:JBoss EAP 6 使用 HornetQ 作为 JMS Provider。
(2)HornetQ 使用 connectors 和 acceptors。其中,
connector 定义了 JMS Client 如何连接到 HornetQ server。
acceptor 定义了 HornetQ server 接受哪种类型的连接。
分别有两种类型的 connector 和 acceptor。
(1)invm: Intra Virtual Machine,client 和 server 在同一个 JVM 中。
(2)netty: client 和 server 在不同的 JVM 中。
注意,connector 和 acceptor 必须匹配使用,invm connector 只能连到 invm acceptor;netty connector 只能连接到 netty acceptor。
(3)Connection Factory:为 connector 定义了一系列的配置参数,总共有35个。
默认定义了两个 InVmConnectionFactory 和 RemoteConnectionFactory。
 (4)durable:A durable destination is one where a receiver can retrieve a message that was sent while the receiver was not active.
默认情况下, Queue是 durable的,Topic是非 durable 的。

2. 演示
(1)cp standalone-full.xml standalone-full-jms.xml
(2)vim standalone-full-jms.xml
   <jms-queue name="myQueue">
      <entry name="java:jboss/queue/myQueue"/>
      <durable>true</durable>
   </jms-queue>
   <jms-topic name="myTopic">
      <entry name="java:jboss/topic/myTopic"/>
   </jms-topic>
(3)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-full-jms.xml -Djboss.socket.binding.port-offset=10000
(4)部署 JMSTest.war
(5)访问:http://localhost:18080/JMSTest/run

Connection Factory JNDI name:   java:/ConnectionFactory
Destination JNDI name: java:jboss/queue/myQueue 或 java:jboss/topic/myTopic

这里的Connection Factory JNDI name 不能使用 java:jboss/exported/jms/RemoteConnectionFactory,这个用于远程JMS调用,需要验证。
前缀java:jboss/exported/表明这个资源可以被客户端找到,即使不在EAP这个容器中。
 
3. JMSTestServlet.java

package com.jboss.jms;

import java.io.IOException;
import java.io.PrintWriter;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class JMSTestServlet
 */

public class JMSTestServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
     
    /**
     * @see HttpServlet#HttpServlet()
     */
    public JMSTestServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Display the JMSTest HMTL form
        request.getRequestDispatcher("jms_form.html").include(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("

Results of JMSTest

");
        String factoryName = request.getParameter("factoryName");
        String  destName = request.getParameter("destName");
        Context context = null;      
        ConnectionFactory connectionFactory = null;
        Destination dest = null;
        out.println("Looking up Connection Factory: " + factoryName + "
");
        try {
            context = new InitialContext();
            connectionFactory = (ConnectionFactory) context.lookup(factoryName);
        } catch (Exception e) {
            out.println("Connection Factory lookup failed: " + e.getMessage() + "
");
            e.printStackTrace();
            return;
        }
        out.println("Successfully found Connection Factory: " + factoryName + "

");
        out.println("Looking up Destination: " + destName + "
");
        try {
            dest = (Destination) context.lookup(destName);
        } catch(Exception e) {
            out.println("Destination lookup failed: " + e.getMessage() + "
");
            e.printStackTrace();
            return;
        }
        out.println("Successfully found Destination: " + destName + "
");
        //If we get this far, both the factory and destination have been found successfully,
        //so let's send a few test messages
        int numOfTests = Integer.parseInt(request.getParameter("numOfTests"));
        if(numOfTests > 0) {
            out.println("Attempting to send " + numOfTests + " test messages to destination...
");
            try {
                Connection connection = connectionFactory.createConnection();
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageProducer producer = session.createProducer(dest);
                TextMessage message = session.createTextMessage();
                for(int i = 1; i <= numOfTests; i++) {
                    message.setText("This is test message " + i);
                    out.println("Sending test message: " + i + "
");
                    producer.send(message);
                }
            } catch(Exception e) {
                out.println("An exception occurred while sending test messages: " + e.getMessage() + "
");
            }
        }
    }

}

2015年9月29日星期二

EAP_033:EAP 6 功能演示 3:日志管理

环境:JBoss EAP 6.4

日志由 Logging Subsystem 负责管理和定义。

1. 日志的3个组件
(1)Handlers: 定义事件将在哪里以及如何被记录。
    默认情况下,定义了两个Handlers:
    CONSOLE: 记录事件到控制台窗口
    FILE: 记录事件到文件:server.log.
(2)Loggers: 日志记录器,按不同目录划分事件。
(3)Root Logger: 根日志记录器,所有日志记录器的根。

2. 日志级别
(1)FATAL: a fatal event means the service cannot continue.
(2)ERROR: a problem that may or may not cause the service to continue running.
(3)WARN: a potentially harmful event has occurred.
(4)INFO: nothing went wrong - just an informational event. 默认的日志级别
(5)DEBUG: extra information useful for debugging errors.
(6)TRACE: allows for deep probing of the JBoss server behavior.

3. 日志文件的位置 

3.1 Standalone Mode:[eap_install_dir]/standalone/log
(1)gc.log.0.current 关于这个文件的具体配置在 standalone.sh中。
(2)server.log 可以按时间或大小滚动该日志文件,关于这个文件的具体配置在standalone.xml中的logging subsystem 中。

3.2 Domain Mode
(1)domain/log/host-controller.log 记录 Host Controller(Domain Controller) 启动时的事件。
(2)domain/log/process-controller.log 记录 启动和停止本机进程时的事件。
(3)domain/servers//log/server.log 记录每个server的事件。

3.3 日志的环境变量:jboss.server.log.dir
jboss.server.log.dir 的位置相对于 jboss.server.base.dir,一般来说只需修改后者即可。


4. 内置的6个Handlers 
注意:Handler 自身不能激活,需要定义在<logger>或<root-logger>中才能激活。

(1)Console handler

写到控制台的handler,定义在 <console-handler> 中。
    <console-handler name="CONSOLE" autoflush="true">
           <level name="INFO"/>
           <formatter>
             <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
           </formatter>
    </console-handler>

(2)File handler
 
写到文件的handler,定义在 <file- handler> 中。

(3)Periodic-rotating file handler
  按时间滚动的文件handler,定义在 <periodic-rotating-file-handler> 中。
<periodic-rotating-file-handler name="FILE" autoflush="true">
    <level name="INFO"/>
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="server.log"/>
    <suffix value=".yyyy-MM-dd"/>
</periodic-rotating-file-handler>
其中,suffix 定义多长时间滚动一次日志,yyy-MM-dd表示一天滚动一次,yyy-MM-dd.HH表示一小时滚动一次,yyy-MM表示一个月滚动一次。

(4)Size-rotating file handler

按大小滚动的文件handler,定义在 <size-rotating-file-handler> 中。
<size-rotating-file-handler name="FILE_BY_SIZE" autoflush="true">
    <level name="INFO"/>
    <encoding value="UTF-8"/>
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="production-server.log"/>
    <rotate-size value="2048"/>
    <max-backup-index value="3"/>
</size-rotating-file-handler>
其中,滚动大小 2048K,即2M。最多保留3个备份日志,加上一个当前的日志。


(5)Async handler
异步记录handler,
它不是一个独立的handler,它只是给现有的handler添加上异步的特性。
定义在 <async-handler> 中。
<async-handler name="ASYNC">
    <level name="INFO"/>
    <queue-length value="1024"/>
    <overflow-action value="BLOCK"/>
    <subhandlers>
        <handler name="FILE"/>
    </subhandlers>
</async-handler>
在 <subhandlers></subhandlers>之间可以增加很多handler。
overflow-action 定义当日志队列满的情况下,如何处理新来的事件,BLOCK 阻止直到有了新的空间,DISCARD,丢弃。 


(6)Syslog handler
允许多个应用发送事件信息到远程日志服务器,具体怎么使用还有待实验验证。

定义在 <syslog-handler> 中。
<syslog-handler name="SYSLOG">
    <level name="INFO"/>
    <server-address value="172.25.2.9"/>
    <hostname value="student2"/>
    <port value="514"/>
    <app-name value="MY_APP"/>
</syslog-handler>
 

5. Loggers
Handlers 定义“在哪”和“如何”记录一个事件,Loggers定义“内容
(日志分类)”和“何时(日志级别)”记录一个事件。

(1)例子1
<logger category="org.jboss.seam">
    <level name="INFO"/>
    <handlers>
        <handler name="FILE"/>
    </handlers>
</logger>

(2)例子2
<logger category="org.apache">
    <level name="WARN"/>
</logger>
<logger category="org.apache.naming">
    <level name="ERROR"/>
</logger>
默认情况下,在Sub Logger中发生的事件,在Parent Logger中也会记录一遍,如果不想在Parent Logger中记录的话,可以在Sub Logger中设置use-parent-handlers = false。

(3)Root Logger
默认情况下,所有的Logger定义,都继承root logger的定义。
没有被Logger定义涉及的事件,都将按照以 root logger的定义来作用。
<root-logger>
    <level name="INFO"/>
    <handlers>
        <handler name="CONSOLE"/>
        <handler name="FILE"/>
    </handlers>
</root-logger>


在生产环境中,Root Logger 建议如下设置:
<root-logger>
    <level name="ERROR"/>
    <handlers>
        <handler name="FILE"/>
    </handlers>
</root-logger>
 

6. 演示

6.1 定义 

(1)cp standalone.xml standalone-logger.xml
(2)vim standalone-logger.xml

 <size-rotating-file-handler name="FILE_BY_SIZE_ROTATING" autoflush="true">
                <level name="ERROR"/>
                <file relative-to="jboss.server.log.dir" path="production-server.log"/>
                <rotate-size value="1m"/>
                <max-backup-index value="3"/>
                <append value="true"/>
  </size-rotating-file-handler>

  <logger category="com.jboss.logtest" use-parent-handlers="false" >
                <level name="INFO"/>
                <handlers>
                    <handler name="FILE_BY_SIZE_ROTATING"/>
                </handlers>
  </logger>


  <async-handler name="ASYNC">
                <level name="INFO"/>                 
                <queue-length value="1024"/>
                <overflow-action value="block"/>
                <subhandlers>
                    <handler name="FILE_BY_SIZE_ROTATING"/>
                </subhandlers>
 </async-handler> 


6.2. 启动EAP,部署LogTest.war

./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-logger.xml -Djboss.socket.binding.port-offset=10000
 

6.3 访问:http://localhost:18080/LogTest/run
(1) 观察Console,发现没有任何应用的日志输出
这是因为use-parent-handlers = false,如果=true,Console中也会有应用日志信息,并且是INFO级别的,因为Root Logger是INFO级别的。
(2) 观察product-server.log,发现有如下输出:
10:27:30,282 FATAL [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is fatal event number 1
10:27:30,282 ERROR [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is error event number 1
10:27:30,283 FATAL [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is fatal event number 2
10:27:30,283 ERROR [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is error event number 2
这是FILE_BY_SIZE_ROTATING handler定义的日志级别是ERROR,而com.jboss.logtest logger 使用的就是这个handler。
也就是说,为每个应用定义自己的日志文件在JBoss EAP 中非常简单。
 (3)以异步的方式写文件

6.4. LogTester.java

package com.jboss.logtest;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.logging.Logger;

/**
 * Servlet implementation class LogTester
 */
public class LogTester extends HttpServlet {
    private static final long serialVersionUID = 1L;
    //private static final Log log = LogFactory.getLog(LogTester.class);
    private static final Logger log = Logger.getLogger(LogTester.class);


    /**
     * Default constructor.
     */
    public LogTester() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.write("

LogTester Application Version 1.0

");
        out.write("Loading this page generates multiple log events for the com.jboss.logtest category.
");
        out.write("Simply reload this page to generate all the log events again.
");
        out.close();
        for(int i = 1; i <= 20; i++) {
            log.debug("This is debug event number " + i);
            log.fatal("This is fatal event number " + i);
            log.info("This is info event number " + i);
            log.error("This is error event number " + i);
            log.trace("This is trace event number " + i);
            log.warn("This is warn event number " + i);
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

}


2015年9月2日星期三

MAC_037:刻录iso

环境:MAC OS X 10.10.5 + LG 外接USB光驱

1. 点击.iso文件,会自动解压并mount该iso文件

2.打开实用工具->磁盘工具,会发现已经mount的iso文件

3.  右键iso文件,选择刻录....

2015年9月1日星期二

MAC_036:使用FileZilla上传文件到AWS EC2

环境:MAC OS X 10.10.1 + FileZilla 3.9.0.6 + AWS EC2

首先在AWS EC2上运行一个Instance,我这里是RHEL 7,具体步骤可以参考文献1。

1. 然后打开FileZilla,选择“设置”,连接->SFTP,上传你的AWS私钥。
AWS秘钥的格式是pem,这里会提示你转换为ppk格式,点击同意转换。


2. 在FileZilla中,选择“站点管理器”,增加一个新的站点,指向你的EC2 Instance的公网IP地址,配置如下:

3. 使用 ssh -i maping-aws.pem ec2-user@54.65.157.224 连接到你的EC2 Instance。
安装 vsftpd,并设置上传目录:/var/www$ sudo yum install vsftpd
$ sudo useradd -s /sbin/nologin -d /var/www/ -g ftp ftpadmin
$ sudo passwd ftpadmin
$ sudo chmod 777 /var/www/ -R

4. 在FileZilla中连接到你的EC2 Instance,现在应该可以上传文件到/var/www目录了。

参考文献:
1. http://blog.banban.me/blog/2014/06/09/li-yong-awsmian-fei-zhang-hu-da-jian-vpn/
2. http://hahagood.com/blog/2013/01/05/aws-ec2%E4%B8%8Eftp/
3. http://www.qiongbupa.com/archives/774