레이블이 spring-security인 게시물을 표시합니다. 모든 게시물 표시
레이블이 spring-security인 게시물을 표시합니다. 모든 게시물 표시

2021-07-24

0724 만들어진 토큰을 api에서 검증하기

 1. ApiLoginFilter에서는 토큰을 만들어주고 (content 에 useremail을 추출해서 넣어주기)

2 . ApiCheckFilter에서는 만들어진 토큰을 검증해서 email이 있을시에만 자원을 보여준다


인증성공시 generateToken을 하고


토큰을 확인해서 email이 있다는 것은 인증을 완료했다는 것!


복호화된 토큰을 Authorization 헤더에 함께 보내면 자원요청에 대한 응답을 확인할수있다

0724 JWT 토큰을 생성하고 검증하기

 


토큰을 생성하는 메소드(위)

토큰을 검증하는 메소드(아래)

를 각각 만든다.

토큰은 : header - payload - signature의 세부분으로 나뉜다.

header에는 contenttype등의 정보,

payload에는 실제 데이터 (이것들을 모아서 claims라고 부른다)

signature는 보안을 위한 암호화 키를 넣는다.

토큰의 만료시간을 설정해야 한다. 다중로그인으로 인한 보안위험을 막기 위한 최소한의 조치. 토큰은 stateless하게 사용되고 session이라는 개념이 없기 때문이다. 또 다른 곳에서 로그인이 되었을때-검증하기가 어렵다.

토큰을 만들때는 compact()메소드를 사용해서 꽉! 묶어주고.

토큰을 검증할때는 parser()메소드를 사용해서 내용을 풀어헤친다.


테스트를 통해 토큰 안의 내용을 확인해 볼 수 있다. 



생성된 토큰을 jwt.io페이지에 넣고 키를 입력하면 - Signature Verified메시지를 확인할 수 있다.



-----------------------------------

만약에 expireDate를 조정한다면 어떻게 될까?


expire를 1초로 해보자!!


그렇다면 위와 같이 토큰이 유효하지 않음을 알려주는 에러 메시지를 확인할 수 있다.

0724 api 인증 처리하기

 Represents the token for an authentication request or for an authenticated principal once the request has been processed by the AuthenticationManager.authenticate(Authentication) method.

Once the request has been authenticated, the Authentication will usually be stored in a thread-local SecurityContext managed by the SecurityContextHolder by the authentication mechanism which is being used. 




api 로그인 페이지를 호출->

request로부터 email과 패스워드를 받아서 -

일치할경우 authentication Manager에게 토큰을 넘겨준다.

그러면 토큰이 security context에 저장된다.

post로 바디에 email과pw를 넣어서 보냈을 경우 -> 인증 OK. 
(다만 현재는 /루트로 가는 페이지가 없어서 404가 뜬다)



틀린패스워드를 넣을경우 -> 인증이 안되었다는 오류메시지를 확인할 수 있음.


0724 api check filter 만들기

 1. api check filter의 역할:

자원이 있는 api의 uri가 들어오면 - 가로채서

authorization 헤더를 체크한다.

헤더에 잘 값이 들어와있으면 인증이 완료된 사용자라는 뜻이므로 다음 filter로 chain하고,

아닌경우 json 에러메시지를 status코드와 함께 전송한다.


헤더에 authorization을 넣어보낸경우 - 자원을 응답 받을 수 있다


authorization 없는경우 - 에러코드와 메시지를 전송한다 response.getWriter를 이용한다.


apicheckFilter는 
pattern이라는 이름의 String을 멤버변수로 가지고 있다.
Securityconfig에서 생성자 멤버변수로 api uri를 넣어준다.
api/**/* 이런식으로!
그래서 해당 patter에 일치할 경우 이 필터를 타고, authorization을 검증한다.



맄리퀘스트 헤더에서 해당 키 (Authorization)을 뽑아서 검사한다.

2021-07-23

0723 Spring Security이해하기

 AuthenticationManager가 적절한 AuthenticationProvider를 선택.

AuthenticationProvider는 다양한 전략으로 구현되어 있음

그중에 쓰게 되는 것은 역시 데이터베이스 기반의 DaoAuthenticationProvider 이다.


UserDetailsService는 AuthenticationProvider가 내부적으로 이용하는 객체이다.(has-a관계)

해당 서비스를 바로 @Service어노테이션만 붙여서 빈 등록 가능.

결론적으로 - 해당 UserDetailsService를 구현하는 것으로 - DB인증이 가능해지게 된다!!
아니면 - SecurityConfig클래스에서 configure 메소드의 AuthenticaitonManagerBuilder에게 던져줘도 된다. 굳이 안써도 @Service어노테이션으로 간편하게 등록하자~~!!

2021-06-30

0630 쿼리 날린 후 무한대기 현상 해결!

 분명히 아까 테스트 잘되는걸 확인했고 파라메터도 잘 받았는데 무한정 대기하고 result가 나오지 않는 현상이 있었다.

https://heewon26.tistory.com/30


<<이분의 글이 정말 도움이 되었다!!

바로 내가 sqldeveloper에서의 변경사항을 커밋하지 않아서.... 그다음 차례가 올때까지 무한정 대기하고 있던 것이다...!!

2021-06-25

0625 스프링 시큐리티 jsp, controller에서 사용하기

<JSP 부분> 

1.  로그인 하지 않은 사용자에게 보여주고 싶을때 

<sec:authorize access="isAnonymous()"> </sec:authorize>

2. 로그인 한 사용자에게 보여주고 싶을때

<sec:authorize access="isAuthenticated()"> </sec:authorize>

3. 로그인 한 사용자의 정보를 뽑아내고자 할때

<sec:authentication property="principal.memberDTO.mName" />

이런식으로 사용할 수 있습니다.

principal은 스프링이 User를 spring security context(스프링이 관리해주는 세션)에 등록하는 변수명입니다.


인터페이스 타입의 UserDetails를

User클래스가 구현하고

User 클래스를 extends하는 CustomUser 클래스를 만들었고

CustomUser 클래스는 멤버변수로 우리의 MemberDTO를 가지고 있습니다. (헥헥..)


즉 getPrincipal(=UserDetails => User =>CustomUser)  -> getMemberDTO -> getMName 의 순서로 변수를 가져오게 되는 것입니다. 동일한 방식으로 MemberDTO의 다른 변수들도 뽑아낼 수 있습니다. @Data어노테이션으로 getter setter를 미리 만들어 두었으니까요! (이메일, 권한 등등.)


4. 로그인한 사용자의 이메일 정보를 뽑아내어 input값을 박아놓기



이런식으로 활용할 수 있습니다.

글을 등록할때 유저가 임의로 본인의 이메일을 조작하지 않도록 readonly를 걸어줍니다.


5. 현재 로그인 한 유저 = 해당 글을 쓴 유저일때만 modify버튼을 보여주기

                                  +

    ADMIN유저는 모든 항목에 접근가능하도록 보여주기




var 로 해당 로그인한 유저의 이메일을 변수로 만든뒤

해당 로그인한 유저(loginUser) = 해당 글을 쓴 유저( dto.mEmail) 일때만 버튼이 보이도록 if문으로 검사 합니다.

혹은 

mGrade를 변수로 받아서 ADMIN일때도 수정,삭제가 가능하도록 합니다.


동일한 작업을 read, modify페이지 둘다 해줍시다.



6. ajax의 하드코딩한 mEmail변수를 수정하기





<Controller 부분>

1. 유저정보를 확인하고 싶을때

Authentication 이라는 타입을 이용하여 뽑아낼 수 있습니다.


이런식으로... 확인할 수 있습니다.

로그 찍어가면서 원하는 변수를 겹겹이 빼내면 됩니다!


2. @GetMapping 접근제어하기

jsp에서 버튼을 숨기더라도 url을 이미 알고있다면 유저는 해당 페이지에 접근할 수 있습니다. 따라서 백엔드에서도 이것을 막아주어야합니다.

@PreAuthorize("isAuthenticated()")

어노테이션을 활용하여 로그인 한 유저만 글을 등록할 수 있게 합니다.



동일하게, RestController에도 접근제어를 걸어줍니다.


3. @PostMapping 접근제어하기

로그인한 유저==해당 글을 등록한 유저

or

권한 ==ADMIN

일 경우에만 글을 수정, 삭제 할 수 있도록 @PostMapping부분을 접근제어해줍니다.

툴을 사용하면 GetMapping을 막아둔 경우에도 @PostMapping으로 접근하여 글을 수정,삭제할수있기 때문입니다.




2021-06-14

0614 메서드 수정

 

1. 파일 이름 받을때 한번 더 거른다. 



2. 메서드에 throws Exception 걸어서 혹여나 Exception발생시 프레임워크가 처리해줄수있도록 수정. service관련 메서드에도 전부 추가함!!

2021-06-13

0613 배운 것들

 1. getOriginalFileName()메소드 문제 : 

        해당 파일명에 공백 이나 .(점) 혹은 /(슬래쉬)같은 문자가 포함되어있을경우 .. 저장했을때  원하지 않았던 결과가 초래될 수 있음!! 상위 디렉토리로 계속 올라가서 공격한다든지..!! 따라서 이 메소드를 그대로 사용하지 말고 파일이름을 한번 걸러내거나- 혹은 filename은 빼고 uuid로만 서버에 저장하고, filename은 db컬럼으로만 저장해서 사용자에게 보여줄 때는 filename만 표시한다. 

        ex) ././././aaa.jpg

2. 사용자 정의 Exception과 RunTimeException 

3. 불필요한 try - catch를 지우고 프레임워크가 Exception을 처리해주도록 throws하기(더욱 간결한 코드!)

프레임워크는 - 내가 만든 코드를 실행해준다. Exception날 수 있는부분만 try catch로 감싸서 해결할 생각 x ,( try catch이외의 부분에서 오류나면 어떡할거얏.) 그냥 throws하고- 프레임워크가 handle해주도록 맡긴다. 그것이 프레임워크의 역할이고 장점!


4. OS는 사용자가 올리는 파일이 그림파일인지 무언지.. 그런 종류를 인식할 수 있어서는 안된다. 그냥 하나의 String으로만 인식해야 한다. 그렇지 않으면 OS가 넘 똑똑해서 '앗 그림파일이다 읽어들여야지~~'하고 메모리에 올렸는데 그순간 악성코드 실행!! 같은 결과가 초래될 수 있다. (버퍼 오버플로우 공격) 따라서 그냥 File그 자체로 저장하고, 암호화하는 것이 좋다. 

5. 

GET: 정적자원 호출 , HTML의 캐시기능을 활용하여 좀더 빠르게 응답

POST: 동적자원 호출 , 동적으로 변경되는 서비스를 제공하고 싶을 때 사용하는 메서드

6. 응집도란 ? 하나의 모듈이 가질 수 있는 기능들이 모아진 정도

7. 패키지 묶을 때: 도메인 별로 묶고 . 만약에 어떤 service가 다른 도메인과 연관되어 비지니스 로직을 수행한다면 - 해당 repository 혹은 mapper를 has a로 껴안는게 아니라. 해당 도메인 소속의 service를 가져와서 이용하자. service 끼리는 맘껏 불러두 된다 ㅎㅎ!! 사용자에게 제공하는(노출되는) 기능이므로.

8. SQLlite??알아보기. 개발환경과 운영환경에서의 다른 DB -> 이거 application - profile명 - properties 파일로 뭔가 조절할 수 있을 듯한?!!

2021-06-06

0606 지속적인 개선



 


피드백을 받은 후 개선한 점

1. 마이바티스&JPA를 같이 사용하기

1) JpaTransactionManager로 트랜잭션 한번에 관리
2) Xml환경 & 자바코드 환경의 장점을 둘다 활용하여 다양한 방식의 DB접근이 가능하도록 설계
3) JPA가 쿼리방언을 자동적으로 조정해주고, CRUD기본 쿼리를 자동적으로 제공해준다는 것은 커다란 장점임. but.. DB는 항상 업데이트되며,(쿼리 방언이 바뀐다든지) JPA라는 오픈소스에만 의존해서는 요구사항에 제때제때 응답할 수 없게 됨!! 여러 상황에 대처할 수 있도록 만들어야함! 


2. 보안강화 
1) modify 게시글 할 때 접근제어의 강화
2) View단에서의 접근 방지& 
3) backend에서는 @PreAuthoried로 @PostMapping 방지 & 
4) DB에서 한번 더 해당 게시글 조회한 후 username과 비교, 설령 username을 조작하더라도 수정이 불가능하도록 한번 더 방지!!

----------------그외, 피드백을 듣고 조사한 사항
오류 메시지를 개발자, 사용자에게 분리해서 보여줄수있을까? -> 스프링의 application-properties파일을 이용해서 환경변수를 조절할 수 있을거같은데!!

0606 스터디

 1. 상속이란 - 부모의 기능을 이용하는 것이지, 멤버변수를 재사용하려고 생각하면 파급효과가 커진다. 상속대신 Has a를 이용해서 기능을 사용하는 방식을 생각해보자.

2. 레인보우 테이블? https://badwood.tistory.com/121

3. @getMapping 충돌시 : java.lang.IllegalStateException: Ambiguous mapping found.

라는 오류가 뜨면서 서버 실행 안됨. uri중복방지 --> 어떻게 해결하지??

4. 도커란? 경량화된 어플리케이션 가상화 기술.

5. 특정시간에 따라 안내페이지로 이동시키기 / 개발중인 경우 안내페이지로 이동시키기

: 스프링 @Profile어노테이션 활용 -> 환경변수(export로 전달하거나) . 

https://2ham-s.tistory.com/259 <<런타임환경을 조절. develop환경인지, 배포환경인지- 조절가능. 올리는 Bean을 다르게 만들 수 있다. 

아니면 - @ConfigurationProperties를 이용해서, 매개변수를 다르게 전달하거나. 


6. 프레임워크란? 절반만 만들어진 소프트웨어, 그 자체로 실행 가능하다. 나머지 절반을 채우는 것은 개발자의 몫! ( 라이브러리와는 다르다, 실행불가능)

7. 접근제어 정책을 뷰~컨트롤러 바로 연결하기(중복코드 제거)? 

2021-06-02

0602 modify, remove 처리

 

1. get으로 유저가 페이지를 불러오더라도 remove, modify 버튼이 안보이도록 제어

자바스크립트로 안보이게했는데. 이거 괜찮을까? 하는 걱정은 있다... sec: authentication으로 값을 가져오려고 했는데 자꾸 문법에러나구. null익셉션 터지기도 해서.. 일단은 이렇게 해본다. 



2. user1@mail.com 인 유저가 modify페이지를 불러왔을 때의 화면



3. user100@mail.com ( 글을 등록한 유저) 가 modify페이지를 불러왔을때의 화면



4. post방식의 전송은 backend단에서 막아주도록 한다. 


-------------------------------------------------------------------------


자바스크립트로 버튼 숨기기 꼼지락하던 코드를

Spring el + thymeleaf의 if태그로 해결했다!!! 더 코드가 간결해졌다. ㅜwㅜ 감격......감격......

0602 register 페이지 처리

 




로그인 한 사용자만 글을 등록할 수 있도록 @PreAuthorized처리하고

해당 유저정보를 view에 보낸다


로그인 한 유저의 이메일이 value값으로 들어가며 readonly를 걸어서 임의로 이메일명을 작성할 수 없도록 한다

0602 @PreAuthoried로 메소드 별 처리하기

원인을 아직 파악하지 못했지만 - 

hasRole표현식이 먹질 않는 문제가 있다


표현식을 바꾸었더니 잘 된다...
왜지...왜냐.... 더 알아보아야 겠음.

--------------------------------------


에러해결!!


권한설정할때 상수값으로 "ROLE_"을 붙여줘야 하는데 이걸 빼먹어서였다!!!



@PreAuthorize("hasRole('USER')")
@PreAuthorize("hasRole('ROLE_USER')")

둘다 시도해봤는데 둘다 가능함!!

0602 로그인/로그아웃 HTML처리

 1. HttpResponse로 redirect썼는데 에러가뜬다- 다른 페이지로 넘어가질 못하고 흰 공백이. 

지우고 다시!!! 페이지 단에서 조절해야겠다


2. 수정후


3. Security context안에있는 객체를 @AuthenticationPrincipal 어노테이션을 활용하여 손쉽게 뽑아낼 수 있음. 로그인 한 유저가 또 로그인 하려고 강제 /customLogin 페이지 접속시의 문제



4. 따라서 sec:authenticate 태그를 이용하여 만일 유저가 로그인한 상태라면 ( = 인증, authentication 이 완료된 상태라면) 해당유저의 name을 보여주도록 , 

인증되지 않은 유저인 경우에만 로그인 화면을 보여주도록 분기


5. 또한 헤더의 url도 인증완료한 유저/익명유저에 따라 분기하여 보여줄수있도록 설정한다. 


6. 만일 로그인한 유저가 강제적으로 /customLogin에 접속하면 로그인 폼이 아니라 위와 같은 화면을 보여준다. 또한 헤더부분의 nav bar에 logout이라는 a태그만 보이는 것을 확인할 수 있다. 

0602 로그인/로그아웃 후 처리

 


1. 기본 인덱스 페이지 ->/board/list로 수정

2. 로그인 페이지에서 error발생시(스프링이 기본적으로 리다이렉트 해줌) -> 메시지표시

3. 로그아웃시 로그인 페이지로 이동(스프링 자동설정) -> 메시지표시

4. 로그인한 유저가 로그인 페이지로 get이동시 -> 로그아웃페이지로 리다이렉트

5. 로그아웃 페이지 설정& 시큐리티 config수정. post로 보내면 나머지는 스프링이 알아서 해준다. 

0602 Spring Security 접근제어

 

1. 로그인한 유저라고 할지라도(인증에 성공하였다고 할지라도) 접근권한이 없는 페이지를 방문하면 자동으로 AccessError페이지로 리다이렉트해주는 AccessErrorHandler를 구현한다. 서블릿의 response를 직접 활용할 수 있다.

2. Security설정파일에 위와 같이 만든 핸들러를 Bean등록하고 http의 exceptionHandling에 맵핑해준다.


3. Controller에 @GetMapping으로 페이지uri를 등록

4. board/list 요청 -> 로그인 페이지 -> board/list로 리다이렉트 -> board/register 요청 -> accessError페이지로 리다이렉트되는 흐름을 알 수 있다. 
핸들러를 구현하지 않아도 스프링이 접근제어를 해주긴 하지만, 커스텀 페이지를 만드는 것이 좋고, 또 redirect를 이용해서 url을 바꾸어 준다.  


2021-06-01

0601 시큐리티 로그인 성공!!!!

1. 로그인 html안에 포함하는 css, js의 경로는 전부 절대경로를 써야한다. 그렇지 않으면 해당 resource를 불러올수없게된다. ( 아니면 securityconfig에서 resource에 대한 설정을 열어두면 된다) 

2. 계속 접근권한에러가 떠서 뭐가 문제일까 했는데, 내가 스프링 security의 구조를 제대로 파악하지 못해서 였다. 



3. authenticated (로그인, 인증) 되지 않으면 - 모든 uri자원에 접근할수없도록 설정(임시, 후에 차차 @PreAuthorized로 세밀한 설정을 할 것임. ) 

4. loginPage는 내가 보여줄 커스텀 로그인 페이지, GetMapping으로 보여주는 로그인 폼이다.

5. loginProcessURL은 스프링이 지정해둔 /login으로 한다. post전송시 여기 url으로 로그인 한 유저의 username(나의 경우엔 email이지만, 스프링의 기본 설정은 username을 식별자로 쓰고 있다)과 password가 날라갈 것이다.

6. 스프링이 username과 password를 내가 커스텀한 UserDetailService를 이용해서 DB에서 유저정보를 읽어올 것이며, 인증에 성공하면 유저가 원래 가고자 했던 uri로 자동 리다이렉트 & 세션에 유저정보를 저장해준다. 



7. 로그인 성공!!!



8. 컨트롤러에서는 @AuthenticationPrincipal이라는 어노테이션을 사용해서 유저객체를 가져올 수 있다.


9. MemberDTO는 노출되는 데이터이므로 role을 멤버변수로 넣지 않는다.

하지만 나의 코딩이 너무 아름다워서 남겨둔다...헤



10. Authorites를 꼭 눈으로 확인해보고싶었기때문에... 어렵사리~~ 코드를 짜서 확인해보았다!!! USER라는 권한이 잘 들어가 있음을 확인할 수 있다!!


11. 절대경로로 리소스를 수정한 후 -> 빌드속도가 또 느려졌다!! 음... 파일을 그냥 없애자. ㅎㅎ css는 나중에 업데이트하면 되니까!!

0328 fdisk, mkfs, mount, fstab

 1. 하드디스크를 붙인다. 2. fdisk -l로 하드디스크를 확인한다.  - interactiive한 커맨드모드 사용하여 (m) 붙인 하드디스크의 파티셔닝을 한다.  - 마지막에 w를 해야 실제로 반영이 된다.  3. mkfs를 하여 어떤 파일시스...