Version 2

    previous part: JBoss AS 7.2.0 - Java EE application development - 05.How to configure Security domain and JAAS - part.1

     

     

    4.User Registration

     

    4.1 war/UserRegisterMBean.java

    @ManagedBean
    @RequestScoped
    public class UserRegisterMBean {
        static final Logger logger = Logger.getLogger(UserRegisterMBean.class.getName());
        @EJB
        private IUserSession userSession;

        @EJB
        private ISensitiveNameSession sensitiveNameSession;
       
        private String username;//登录名
        private String password;//加了Transient注解:仅仅供用户从客户端传递到服务器端以便新增或者修改时使用。
        private String passwordRepeat;
        private String firstname = "";//真实姓
        private String lastname = "";//真实名
        private String mobilePhone = "";//手机
        private String email ="";//电子邮件。
        private String birthday = null;//生日
        private Gender gender = Gender.UNKNOWN;//性别
        //private String imageLink = "unknown.jpg";//头像链接
       
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        ...//other getters/setters
       
        public String create(){
            //check if input valid
            ...      
           
            //build and persist Entity beans
            User user = new User();
            //a:Mandatory fields
            user.setUsername(this.getUsername().trim());
            user.setHashedPassword(HashUtil.createPasswordHash(this.getUsername().trim(), this.getPassword().trim()));
            user.setEmail(this.getEmail().trim());
            //b:Optional fields
            if(this.getBirthday()!=null&&this.getBirthday().trim().length()> 0){
                user.setBirthday(DateHelper.stringToUtilDate(this.getBirthday().trim()));
            }
            user.setFirstname(this.getFirstname());
            user.setLastname(this.getLastname());
            user.setMobilePhone(this.getMobilePhone());
            user.setGender(this.getGender());
            //save to DB
            try{
                userSession.registerUser(user);
            }catch(Exception e){
                String errMsg = "错误:"+e.getMessage();
                JSFHelper.addErrorMessage(errMsg);
                logger.severe(errMsg);
                return Constants.RETURN_FAILURE;
            }
           
            return Constants.RETURN_SUCCESS;
        }
    }

     

    4.2 war/register.xhtml

     

    <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <ui:composition xmlns="http://www.w3.org/1999/xhtml"

                    xmlns:ui="http://java.sun.com/jsf/facelets"

                    xmlns:f="http://java.sun.com/jsf/core"

                    xmlns:h="http://java.sun.com/jsf/html"

                    template="/template/template.xhtml">

     

        <ui:define name="title">

            <h:outputText value="#{messages['ybxiang.javaarm.register']}" />

        </ui:define>

     

        <ui:define name="headMetaData">

        </ui:define>

     

        <ui:define name="body">       

            <h:form id="form" >

     

                <h3><h:outputText value="#{messages['ybxiang.javaarm.register']}"/></h3>

     

                <h:panelGrid columns="2">

                    <h:outputLabel style="color:red" value="#{messages['ybxiang.javaarm.username']}(*)" for="username" />

                    <h:inputText id="username" value="#{userRegisterMBean.username}" maxlength="#{entitiesConstantsMBean.maxUsernameLength}" size="90" >

                        <f:validateLength minimum="#{entitiesConstantsMBean.minUsernameLength}" maximum="#{entitiesConstantsMBean.maxUsernameLength}" />

                    </h:inputText>

                    <h:outputText value=""/>

                    <h:message for="username" styleClass="message" errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/>

                   

                    <h:outputLabel style="color:red" value="#{messages['ybxiang.javaarm.password']}(*)" for="password" />

                    <h:inputSecret id="password" value="#{userRegisterMBean.password}" maxlength="#{entitiesConstantsMBean.maxPasswordLength}" size="90" >

                        <f:validateLength minimum="#{entitiesConstantsMBean.minPasswordLength}" maximum="#{entitiesConstantsMBean.maxPasswordLength}" />

                    </h:inputSecret>

                    <h:outputText value=""/>

                    <h:message for="password" styleClass="message" errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/>

     

                    <h:outputLabel style="color:red" value="#{messages['ybxiang.javaarm.passwordRepeat']}(*)" for="passwordRepeat" />

                    <h:inputSecret id="passwordRepeat" value="#{userRegisterMBean.passwordRepeat}" maxlength="#{entitiesConstantsMBean.maxPasswordLength}" size="90" >

                        <f:validateLength minimum="#{entitiesConstantsMBean.minPasswordLength}" maximum="#{entitiesConstantsMBean.maxPasswordLength}" />

                    </h:inputSecret>

                    <h:outputText value=""/>

                    <h:message for="passwordRepeat" styleClass="message" errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/>

     

                    ...

                   

                    <h:outputText value="."/>

                    <h:commandButton id="submitButton" value="#{messages['ybxiang.javaarm.register']}" action="#{userRegisterMBean.create()}" />

                </h:panelGrid>

            </h:form>

        </ui:define>

    </ui:composition>

     

     

    4.3 HashUtil.java

    请参考:链接 一文。

    public class HashUtil {   

        public static final void testSystemPropertyInEJB(){

            System.out.println("SYSTEM_PROPERTY_KEY_JAAS_hashAlgorithm: "+System.getProperty(ServerConstants.SYSTEM_PROPERTY_KEY_JAAS_hashAlgorithm));

        }

       

        public static final String getHashAlgorithmFromSystemProperty(){       

            return System.getProperty(ServerConstants.SYSTEM_PROPERTY_KEY_JAAS_hashAlgorithm, ServerConstants.DEFAULT_JAAS_hashAlgorithm);

        }

        public static final String getHashEncodingFromSystemProperty(){

            return System.getProperty(ServerConstants.SYSTEM_PROPERTY_KEY_JAAS_hashEncoding, ServerConstants.DEFAULT_JAAS_hashEncoding);

        }

        public static final String getHashCharsetFromSystemProperty(){

            return System.getProperty(ServerConstants.SYSTEM_PROPERTY_KEY_JAAS_hashCharset, ServerConstants.DEFAULT_JAAS_hashCharset);

        }

       

        public static String createPasswordHash(String username, String password){

            return createPasswordHash(

                    getHashAlgorithmFromSystemProperty(),

                    getHashEncodingFromSystemProperty(),

                    getHashCharsetFromSystemProperty(),

                    username,

                    password

            );

        }

       

        public static String createPasswordHash(String hashAlgorithm, String hashEncoding,

                   String hashCharset, String username, String password){

            //method.1

            String result = org.jboss.security.auth.spi.Util.createPasswordHash(hashAlgorithm, hashEncoding, hashCharset, username, password);

           

            //method.2: from http://www.ajka-andrej.com/2011/05/22/jboss-6-client-authentication-sd/

            //String result2 = CryptoUtil.createPasswordHash(hashAlgorithm, hashEncoding, hashCharset, username, password);

           

            return result;

           

        }

    }

     

    4.4 ejb/IUserSession.java

    public interface IUserSession {

        public void registerUser(User user);

        ...

    }

     

    4.5 ejb/UserSession.java

    @Stateless
    @Local(IUserSession.class)
    public class UserSession implements IUserSession{
        @PersistenceContext()
        private EntityManager em;
       
        @EJB
        ICacheService cacheService;
        @EJB
        IEmailService emailService;   
        @EJB
        IJaasCacheSession jaasCacheSession;
       
        ...   
       
        @PermitAll()
        public void registerUser(User user){
            if(isUsernameExist(user.getUsername())){//已经有唯一性限制了
                throw new RuntimeException("该用户名已经备注册(This username already exists)。");
            }
           
            if(user.getEmail()==null){
                throw new RuntimeException("非法电子邮件地址(Invalid email address)。");
            }

            if(isEmailOverRegistered(user.getEmail())){
                throw new RuntimeException("一个电子邮件地址最多只能注册3个账号(One Email can register at most 3 accounts).");
            }
            //
            user.setActivated(false);//改成false,防止JSF MBean那里错误设置为true。测试的时候,我们用“true”,让用户直接处于激活状态。
            em.persist(user);

           
            ActivateCode activateCode = new ActivateCode();
            activateCode.setUser(user);
            activateCode.setCode(RandomHelper.getRandomString(ActivateCode.CODE_LENGTH));
            activateCode.setUsageType(ActivateCode.Usage.USER_ACTIVATE_ACCOUNT.id);
            em.persist(activateCode);
           
            //************************************UPDATE user cache!!!
            cacheService.updateUserCache_ONLY_by_UserSessionOrLocalEJB(user);

            //************************************Send activating code to user's email.
            Email email = new Email();
            email.setTitle(EmailConstants.USER_REGISTER_ACTIVATION_EMAIL_TITLE);
            email.setContent(EmailConstants.getUserRegisterActivatioinEmailContent(user.getUsername(), activateCode.getActivatingLink()));
            email.setToUser(user);
            em.persist(email);
            emailService.sendMail(email);
        }
        ...
    }