Skip to content
isdnetworks
Go back

로그인을 하나로 할지 둘로 할지 정했다

관리자 화면과 협력사 화면을 각각 만들게 되면서 로그인을 하나로 할지 물음이 나왔다.

Table of contents

Open Table of contents

두 쪽이 무엇을 하는지 봤다

관리자는 전체를 본다. 회원 정보와 주문과 정산과 config 까지 다 닿는다. 협력사는 WHERE partner_no = ? 로 자기 것만 본다. 다른 협력사 것은 못 본다.

권한 범위가 크게 달랐고 겹치는 부분이 거의 없었다. 이 차이가 판단의 근거가 됐다.

합칠 때와 나눌 때

합치면 로그인 코드를 한 번만 만든다. password_hashpassword_verify 로 비밀번호를 다루는 자리가 하나다. 잠금과 이력 남기기도 거기서 한다. 관리자가 협력사 화면을 볼 일이 있을 때 다시 로그인하지 않아도 되는 것도 이점이었다.

나누면 권한 실수의 범위가 좁아진다. 하나로 두면 권한 확인 if 하나를 잘못 썼을 때 협력사가 관리자 화면에 들어간다. 나누면 애초에 그 화면이 다른 자리에 있다. 협력사 계정이 유출됐을 때 닿는 범위도 그 안에 갇힌다.

나누기로 했다

grep -rn 으로 두 쪽이 닿는 표를 세어 보니 겹치는 것이 적었다. 밖에서 쓰는 계정과 안에서 쓰는 계정을 섞지 않는 편이 낫다는 것도 이유였다.

접근할 수 있는 자리도 나눠서 관리자 화면은 사내망이나 VPN 에서만 열리게 했다. 앞단의 allow from 만으로 막지 않고 애플리케이션에서 REMOTE_ADDR 도 확인했다. 설정 하나가 빠지면 그대로 열리기 때문이다.

로그인 코드 자체는 비슷해서 AuthCore 로 그 부분만 공통으로 뒀다.

class AuthCore {
    public function attempt($table, $id, $pw);
    public function lockCheck($table, $id);
    public function logAttempt($table, $id, $ok, $ip);
}

attemptlockChecklogAttempt 가 하는 일은 같다. $tableadmin_userpartner_user 냐만 다르다. 로그인을 나누는 것과 로그인 코드를 두 벌 쓰는 것은 다른 이야기였다.

세션도 갈라야 했다. 같은 도메인이면 쿠키가 그대로 공유된다. cookie_path/admin/partner 로 나눠 서로의 세션을 안 보게 했다.

대신 보기를 만들었다

나누고 나니 문의를 처리할 때 관리자가 협력사 화면을 봐야 하는 경우가 생겼다. 협력사 비밀번호를 물어보는 것은 안 될 일이다. password_hash 로 넣어 둔 값은 되돌릴 수도 없다. 그래서 viewAs 를 만들었다.

public function viewAs($partnerNo) {
    if (!$this->admin->isLogin()) { show_404(); }
    $this->session->set_userdata('view_as_partner', $partnerNo);
    $this->session->set_userdata('view_as_admin', $this->admin->id());
    redirect('/partner/');
}

isLogin 으로 관리자인지 먼저 보고 set_userdata 에 담은 뒤 redirect 한다. 화면 위에 대신 보는 중이라는 표시를 두고 그동안에는 POST 를 막았다. 보는 것만 되고 고치는 것은 안 되게 한 것인데 누가 고쳤는지 흐려지는 것을 막으려는 것이었다. view_as_admin 에 담긴 관리자 번호로 누가 언제 어느 협력사 화면을 봤는지도 남겼다.

몇 달 뒤 협력사 계정 하나가 유출된 일이 있었다. 그 계정으로 닿을 수 있는 것이 그 협력사 자료뿐이었다. 하나로 돼 있었으면 권한 확인 코드 하나에 기대야 했다. 나눠 두니 그 코드가 틀렸어도 화면 자체가 다른 자리에 있었다. 막는 것을 한 겹만 두지 않은 것이 그때 값을 했다.

정리


Share this post on:

Previous Post
권한이 없어서 버튼이 안 보였다
Next Post
스크립트가 중간에 멈췄고, 백업본이 사라져 있었다