새소식

반응형
JavaScript/AngularJS

Spring Boot와 Angulrjs(run 메소드를 이용한 로그인 설정

  • -
반응형

Angularjs

1. login.js 및 login.html 생성

* run method를 이용하여 로그인 인증정보를 확인한다.

* angular의 run 메소드는 java의 main 함수 역할

* run 메소드(java에서 main 함수 역할)

app/views/components/login/login.js

angular.module('AuthCheck', [])
.run(['$rootScope', '$window', '$http', function($rootScope, $window, $http){
     if($window.sessionStorage.getItem('currentUser')){
         $http.defaults.headers.common.Authorization = 'Bearer'+$window.sessionStorage.getItem('currentUser')
     }

     $rootScope.$on('$locationChangeStart', function(event, next, current){
       //$locationChangeStart 이벤트는 url이 변경되었을때 반응하는 이벤트다.
         if(!$window.sessionStorage.getItem('currentUser') && url != '/login.html'){
             $window.location.href='login.html'
      //해당 href 경로를 auth.html파일만 적은이유는 app 바로 밑 경로에 auth.html 파일이 존재하기 떄문이다.
         }
     })
}])
.factory('AuthCheckFactory', ['$http', '$window', function($http, $window){
     var service = {};
     service.Login = Login;
     service.Logout = Logout;
     return service; //팩토리는 리턴값이 필수다!

  //login.html에서 로그인된 아이디, 패스워드를 rsa 공개키암호화알고리즘으로 암호화하여 Login을 호출한다.
 
    function Login(k, kk){                   
        $http.post('/api/login', {login_a:k, login_b:kk})
        .then(function(data){           
            if(data.data === '성공'){
                 $window.sessionStorage.setItem('currentUser', data.data.token);
                 //sessionStorage에 토큰값을 설정한 후 location.href로 url 이동
                 $window.location.href='/dashboard';
             }else{
             } 
        })   
    }​

     function Logout(){
         $window.sessionStorage.removeItem("currentUser");
         $http.defaults.headers.common.Authorization = '';
     }

}])

 

 

* login.html 파일을 생성하기전 로그인 데이터 정보를 암호화를 위해 RSA 암호화 사용

* RSA Library 추가

lib.zip
0.01MB

위 그림과 같이 lib.zip 파일을 app/views/components/login 경로에다가 풀어준다.

 

app/login.html

<html ng-app="AuthHtml">
 <head>
         <meta charset="utf-8">
         <title></title>
         <script src="lib/angular/angular.min.js"></script>
         <script src="views/components/login/login.js"></script>
         <script type="text/javascript" src="views/components/login/lib/jsbn.js"></script>
         <script type="text/javascript" src=views/components/login/lib/rsa.js"></script>
         <script type="text/javascript" src="views/components/login/lib/prng4.js"></script>
         <script type="text/javascript" src="views/components/login/lib/rng.js"></script>
         <script>
         <script>
             angular.module('AuthHtml', [
                 'AuthCheck' //login.js 모듈명
             ])
             .controller('AuthHtmlCtrl', ['$scope', '$http', 'AuthCheckFactory', function($scope, $http, 
             AuthCheckFactory){   //AuthCheckFactory는 login.js 팩토리명
                 var rsa = new RSAKey();
                 $http.get('/api/login')
                 .then(function(res){
                     // rsa의 n 과 e 값에 api에서 넘어온 값을 설정
                     // setPublic은 RSAKey()의 prototype 설정
                     // javascript prototype은 제 글에서 찾아보면 설명해놨습니다.

                     rsa.setPublic(res.data.login_a, res.data.login_b)
                 })

                 $scope.login = function(){
                     AuthCheck.Login(rsa.encrypt($scope.id), rsa.encrypt($scope.pass), function(result){
                     if(result){

                     }else{
                         alert('로그인 실패')
                     }
             })
     }
}])
</script>

<body ng-controller="AuthHtmlCtrl">
    <!-- 로그인 화면은 직접 제작해주세요ㅜㅜ -->
    <input id="id" type="text" ng-model="id"><br>     
    <input id="pw" type="text" ng-model="pw"><br>     
    <button ng-click="login()">로그인</button>
</body>

</html>

    

 

 

 

2. 메인 app.js 파일에 생성한 login.js 파일을 주입시켜준다.

app/app.js

 

 

Spring Boot(Java)

LoginController.java

package com.angular.web.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.angular.web.utils.RsaUtils;
import com.angular.web.vo.login.LoginVO;

@RestController
@RequestMapping(value="/api")
public class LoginController {

    @Autowired
    RsaUtils rsaUtils;

    @GetMapping(value="/login")
    public LoginVO loginController() {

        LoginVO vo = new LoginVO();
        vo.setLogin_a(rsaUtils.getPublicKeyModulus());
        vo.setLogin_b(rsaUtils.getPublicKeyExponent());
        return vo;
    }

    @PostMapping(value="/login")
    public String loginController(@RequestBody LoginVO vo) {
        System.out.println("vo a : "+rsaUtils.decrypt(vo.getLogin_a()));
        System.out.println("vo b : "+rsaUtils.decrypt(vo.getLogin_b()));
        /*
         * rsaUtils.decript() 를 통해 복호화 한 후 로그인 값이 맞는지 확인한 후 return 한다.
        */
        return "성공";
    }
}

 

RsaUtils.java

* Java의 RSA 암호화에 관한건 아래의 글에서 확인 가능합니다

https://okimaru.tistory.com/116

 

RSA 암호화 만들기

RSA 암호화 공개키 암호시스템 중 한개, 암호화 뿐만 아니라 전자서명도 가능한 최초의 알고리즘으로 알려진다. RSA는 두개의 키를 사용한다. 공개키와 개인키를 사용하는데 공개키는 평문을 암

okimaru.tistory.com

package com.angular.web.utils;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

import org.springframework.stereotype.Component;

import com.angular.web.utils.Funcs;

@Component
public class RsaUtils {
//공개키
private PublicKey publicKey;
//개인키
private PrivateKey privateKey;

//공개키 및 개인키의 N 값
private String publicKeyModulus;
//공개키 및 개인키의 E 값
private String publicKeyExponent;

KeyPairGenerator gen;

public RsaUtils() {
try {
//1024 RSA 키쌍을 생성
gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(1024);
KeyPair keys = gen.genKeyPair();
publicKey = keys.getPublic();
privateKey = keys.getPrivate();

//만들어진 공개키의 N(Modulus) 값과 E(Exponent)값을 문자열로 가져온다.
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec publicSpec = keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);

publicKeyModulus = publicSpec.getModulus().toString(16);
publicKeyExponent = publicSpec.getPublicExponent().toString(16);

} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
e.printStackTrace();
publicKey = null;
privateKey = null;

publicKeyModulus = null;
publicKeyExponent = null;
}

}

public PublicKey getPublicKey() {
return publicKey;
}

public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}

public PrivateKey getPrivateKey() {
return privateKey;
}

public void setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
}

public String getPublicKeyModulus() {
return publicKeyModulus;
}

public void setPublicKeyModulus(String publicKeyModulus) {
this.publicKeyModulus = publicKeyModulus;
}

public String getPublicKeyExponent() {
return publicKeyExponent;
}

public void setPublicKeyExponent(String publicKeyExponent) {
this.publicKeyExponent = publicKeyExponent;
}

public KeyPairGenerator getGen() {
return gen;
}

public void setGen(KeyPairGenerator gen) {
this.gen = gen;
}

public String decrypt(String secureInfo) {
    String secureDecryptInfo = "";
    try{
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        /**
        * 암호화 된 값은 byte 배열이다.
        * 이를 문자열 폼으로 전송하기 위해 16진 문자열(hex)로 변경한다.
        * 16진 문자열로 변경하기 위해 funcs이라는 utils 이용
        * 서버에서 값을 받을 때 hex 문자열을 받아서 이를 다시 byte 배열로 바꾼 뒤에 복호화 과정을 수행한다.
        */
        byte[] encryptedBytes = Funcs.hexToByteArray(secureInfo);
        if( encryptedBytes == null) return null;
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        secureDecryptInfo = new String(decryptedBytes, "utf-8"); // 문자 인코딩 주의.

        return secureDecryptInfo;
    }catch(Exception e){
        return null;
    }

}

}
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.