SalesforceでWebサイト作成〜ユーザ登録、ログイン作成〜

# **はじめに**
Salesforceの勉強を兼ねて練習用WEBサイトを作成しており、そこで学んだことをまとめました。
今回は、ユーザ登録してログインしてみた☆の巻です！！

## **実装機能**
⑴ 登録した商品を表示
<img width="1417" alt="スクリーンショット 2018-06-01 23.43.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/c695af80-d250-bf36-a1ce-34bdcf75e38c.png">
> 詳細はこちら
> https://qiita.com/szaizen/items/19f3c2b0f531f8fdb00f

⑵ 会員登録、ログイン
<img width="1421" alt="スクリーンショット 2018-06-01 23.45.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/4b72a98b-a15c-35e2-b2ff-4a9e08e7118a.png">

⑶ ショッピングカート的なもの
<img width="1428" alt="スクリーンショット 2018-06-01 23.46.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/efbc91bd-eebb-1b4f-e4e5-12345eb3650e.png">
>詳細はこちら
>https://qiita.com/szaizen/items/e1689446ade8f824b018



# **ユーザ登録**

ユーザ登録をしてログインをする機能を実装していきます。
まず登録されたユーザ情報を保存する先を作成する必要があります。
今回は、標準オブジェクトを使わずに「ユーザ」というカスタムオブジェクトを作成します。

##**カスタムオブジェクト作成（ユーザー）**

▼Salesforceのカスタムオブジェクト「ユーザー」
<img width="797" alt="スクリーンショット 2018-06-02 17.17.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/d056edb3-bd5f-66af-4471-7155ca2a1d9f.png">


▼Visualforceページで作成した新規登録画面
<img width="1667" alt="スクリーンショット 2018-06-02 17.20.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/8585685a-7ef0-5ea9-4020-738c2e0ee07d.png">

▼Visualforceページのコード

```html:Usercreate.vfp
<apex:form >
    <div class="control-form">
        <div class="control-group">
            <label class="control-label" for="">氏名</label>
            <div class="controls">
                <apex:input type="text" html-placeholder="田中太郎" required="true" html-autofocus="false" id="inputNewName" value="{!inputNewName}"/>
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="">メールアドレス</label>
            <div class="controls">
                <apex:input type="text" html-placeholder="music@cc.jp" required="true" html-autofocus="false" id="inputNewEmail" value="{!inputNewEmail}"/>
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="">パスワード</label>
            <div class="controls">
                <apex:inputSecret id="inputNewPassword" value="{!inputNewPassword}" required="true" />
            <div class="help-block">パスワードは6文字以上にしてください。</div>
        </div>
        </div>
    </div>
    <div class="control-group">
        <div class="controls">
        	<apex:commandButton action="{!ContactUser}" value="ユーザー登録する" styleclass="btn btn-primary" />
    	</div>
    </div>
</apex:form>
```

##**Apexクラスでレコード作成**

フォームで入力された氏名などはApexクラスで受け取る必要があり、変数定義をします。
この時には変数名と、inputタグのvalueを同じにしておく必要があります。

また、プレイスホルダー値など設定するためには、最初にHTML5を宣言しておかなければいけないので注意。

▼Apexクラス

```java
//新規ユーザ
public String inputNewName {get; set;}
public String inputNewEmail {get; set;}
public String inputNewPassword {get; set;}

public PageReference ContactUser(){
　　　　　　　　User__c user = new User__c();
    user.Name  = inputNewName;
    user.id__c  = inputNewEmail;
    user.password__c = inputNewPassword;
    insert user;
    return page.UserCreated;
}
```

commandButtonタグのactionで、実装するメソッドを指定します。

戻り値はPageReferenceにして、ボタンを押下したら登録完了のページに飛ばすようにしています。
Userオブジェクトをインスタンス化し、そこに先ほど入力フォームの値を代入している変数を代入していき、最後にINSERTをすれば、レコードが作成されます。

##**実装画面**

▼ユーザ登録してみます
<img width="1664" alt="スクリーンショット 2018-06-02 17.20.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/6e1cf182-bb02-a2be-e29a-299bb80c637a.png">
↓
▼登録完了画面に遷移
<img width="1661" alt="スクリーンショット 2018-06-02 17.21.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/8ceaaf31-de09-6eb4-56d0-275a13067f30.png">
↓
▼ユーザが作成されます
<img width="858" alt="スクリーンショット 2018-06-02 14.26.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/1ebf5c7e-c26c-d3d4-9312-23f8874d4005.png">


#**ログイン機能**

次に、ユーザとセッション情報を使ってログイン機能を作ります。
ちなみに今回はBootstrapのモーダルを使ってログイン画面を作りました☆

##**カスタムオブジェクト作成（セッション）**

セッション情報を保持するオブジェクトを作成します。
<img width="897" alt="スクリーンショット 2018-06-02 17.02.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/c8d4f7a2-1a11-03f5-883d-1d042fef049b.png">


##**Visualforce、Apex**

▼Visualforceページのソース

```html
<a class="modal_login" data-toggle="modal" data-target="#sampleModal">
 ログインはこちら
</a>

<!-- モーダル・ダイアログ -->
<div class="modal fade" id="sampleModal" tabindex="-1">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">M:usic ログイン画面</h4>
                <button type="button" class="close" data-dismiss="modal"><span>×</span></button>  
            </div>
            <!-- モーダル内容 -->
            <div class="modal-body">
				<apex:form >
                    <div class="container">
                        <div class="row">
                            <div class="col-md-3">ID</div>
                            <div class="col-md-9">
                       			<apex:inputText value="{!inputUser.id__c}" />
                            </div>
                   　	</div>
                        <div class="row">
                            <div class="col-md-3">PassWord</div>
                            <div class="col-md-9">
                        		<apex:inputSecret value="{!inputUser.password__c}" />
                            </div>
                   　	</div>
                        <div>
               				<apex:commandButton value="Login" action="{!actionLogin}" />
                        </div>
                    </div>
                    <div class="modal-createuser">
                    新規登録は<a href="{!$Page.UserCreate}">こちら</a>
                 	</div>
            	</apex:form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">閉じる</button>
            </div>
        </div>
    </div>
</div>

```

▼Visualforceページ
<img width="1421" alt="スクリーンショット 2018-06-01 23.45.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/4b72a98b-a15c-35e2-b2ff-4a9e08e7118a.png">

▼Apexクラスのソース

```java

public User__c inputUser {get; set;}    

 /********************************
 * 　　ログイン
 * *******************************/
public PageReference actionLogin() {

    //IDとPasswordをチェック
    User__c user = login(inputUser);
    
    //ユーザ
    if (user != null) {
        String sessionId = generateNewSessionId();
        writeSessionId(user, sessionId);
        writeSessionIdToCookie(sessionId);
        
        render=true;
        return Page.home.setRedirect(false);
    } else {
        removeSessionIdOfCookie();
        return null;
    }
}

public User__c login(User__c inUser) {
    List<user__c> users = [Select Id, id__c, Name, password__c FROM User__c WHERE id__c = :inUser.id__c];
    if (users.size() == 1) {
        User__c aUser = users[0];
        if (aUser.password__c != null && aUser.password__c.equals(inUser.password__c)) {
            loginUser = aUser;
            return loginUser;
        }
    }
    
    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'ログイン失敗'));
    return null;
}


private String generateNewSessionId() {
    DateTime dt = DateTime.now();      
    //現在時刻のMD5ハッシュ値を取得
    return EncodingUtil.convertToHex(Crypto.generateDigest('md5', Blob.valueOf(dt.formatLong())));
}

private void writeSessionId(User__c inUser, String inSessionID) {
    if (inSessionID != null && inUser != null) {
        Session__c session = null;
        List <session__c> sessions = [SELECT ID FROM Session__c WHERE userId__c = :inUser.id__c];
        //既にセッションがある場合は削除
        if (sessions.size() != 1) {
            if (sessions.size() > 0) {
                delete sessions;
            }
            sessions = null;
        }
        //セッションがなければ作成
        if (sessions == null) {
            session = new Session__c(userId__c = inUser.id__c);
        } else {
            session = sessions[0];
        }
        session.sessionId__c = generateNewSessionId();
        session.available__c = DateTime.now().addSeconds(CommonController.releaseTime);
        upsert session;
    }
}

public void writeSessionIdToCookie(String inSessionId) {
    Cookie aCookie = new Cookie(CommonController.theCookieName, inSessionId, '/',  CommonController.releaseTime, true);
    ApexPages.currentPage().setCookies(new Cookie[] {aCookie});

}

public void removeSessionIdOfCookie() {
    Cookie aCookie = new Cookie(CommonController.theCookieName, 'deleted', '/',  -1, true);
    ApexPages.currentPage().setCookies(new Cookie[] {aCookie});
}


```


> 参考サイト:https://devlog.arksystems.co.jp/2017/07/24/3612/


##**ログイン状態の判断**

ログイン後は、そのユーザ情報を持っておく必要があります。
ログイン時にCookieとSalesforceのセッションオブジェクトにセッション情報を書き込んでいるので、コンストラクタでCookie情報を取得してログイン状態を判断することができます。

```java

//ログイン状態
public User__c inputUser {get; set;}    
public User__c loginUser {get; set;} 
public String UserId{get; set;} 
public String UserName {get; set;} 
public boolean render {get; set;} 
public String CookieId ;
public String objectId {get; set;}

 /********************************
 * 　　コンストラクタ
 * ・ログイン状態を判断する
 * *******************************/
public LoginController() {
    inputUser = new User__c();
    
    //クッキー情報を取得
    Cookie get_cookie = ApexPages.currentPage().getCookies().get(CommonController.theCookieName);
    
    //クッキー情報がある場合
    if (get_cookie == null) {
		render = false;
    }else{
        CookieId = get_cookie.getValue();
        List<session__c> session = [Select Id,Name,userId__c, available__c, sessionId__c from Session__c where sessionId__c  = :CookieId];
    
        //セッション情報がSFAにある場合
        if(session.size() == 1){
            render = true;
            List<user__c> user = [Select id__c,Name  from user__c where id__c  = :session[0].userId__c];
            UserName = user[0].Name;
            UserId = user[0].Id;

        }
    }

            
}
```

##**ページの出し分け（rendered）**

renderのBoolean値は、ログイン状態でヘッダーを出し分けるための変数です。

```html
<apex:outputPanel rendered="{!NOT(render)}">
	<c:Music_header />
</apex:outputPanel>
<apex:outputPanel rendered="{!render}">
	<c:Login_header />
</apex:outputPanel>
```

このように、renderがtrueかfalseかで表示するVisualforceコンポーネントを変えています。

>参考サイト:http://mnakayama.hatenablog.com/entry/visualforce_rendered_sample

また、UserNameに名前を代入しているため、下記のように記述をすると名前を表示することができます。
これを使って、ヘッダーの名前を変えています。


```
こんにちは{!UserName}さん
```

<img width="281" alt="スクリーンショット 2018-06-02 14.51.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/e4cd415e-7ff8-de96-fc24-0a21915fae3c.png">


##**ログアウト**

ログアウトの時は、セッションIDにlogoutと文字列を書き込んでログインできないようにしています。
ログイン時の動きとして、セッションIDとCookieIDが一致したらそのユーザにログインするような記述をしているので、
セッションIDが一致しないものに変更したらログインできないじゃん！と思いこの実装にしていますが、多分もっといい方法あると思います、、

```java

public PageReference logout() {
    session__c session = [Select sessionId__c from Session__c where sessionId__c = :CookieId limit 1];
    session.sessionId__c  = 'logout';
    system.debug(session);
    update session;
    return page.home.setRedirect(true);
}    
```

##**実装画面**
▼ログイン画面
<img width="548" alt="スクリーンショット 2018-06-02 17.15.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/0e08d0a7-3861-2141-dc39-fb8c305b56f9.png">
↓
▼ログイン後のホーム画面
<img width="1665" alt="スクリーンショット 2018-06-02 17.15.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/a89f63af-60f6-4cae-f97e-5dd4cee6ca8d.png">

<img width="254" alt="スクリーンショット 2018-06-02 17.16.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/240803/bc405099-dddf-ed8b-3f37-0665c2e8fd68.png">



とりあえずログインとログアウトの動きはできました。
次はショッピングカートの実装です☆

#**参考サイト**
>そるでぶろぐ Force.comの少し偏った教科書 : 3.Sitesにセッションを実装する
>https://devlog.arksystems.co.jp/2017/07/24/3612/

>MNakayamaのブログ apexのrenderedプロパティで表示コンテンツを切り替える
>http://mnakayama.hatenablog.com/entry/visualforce_rendered_sample



コードはこちらです〜
https://github.com/szaizen/music