Category: Spring Security

0

Spring Security - Security 설정을 위한 WebSecurityConfigurerAdatper

목차 Spring Security 권한 계층 사용하기 - @RoleHierarcy Spring Security - DelegateFilterProxy Spring Security - Remember Me와 관련된 인증 API - RememberMeConfigurer Spring Security - RembmerMeAuthenticationFilter Spring Security - SessionManagementFilter & ConcurrentSessionFilter Spring Security - 인가 API ExpressionUrlAuthorizationConfigurer Spring Security - Security 설정을 위한 WebSecurityConfigurerAdatper Spring Security - AuthenticationProvider Spring Security - AuthenticationManager Spring Security - UsernamePasswordAuthenticationFilter & AbstractAuthenticationProcessingFilter Spring Security - SecurityContextHolder 와 SecurityContext Spring Security - Authentication 객체 Spring Security 설정하기 - WebSecurityConfigurerAdatper스프링 Scurity에 대한 설정은 WebSecurityConfigurer 인터페이스 구현하거나 WebSecurityConfigurerAdapter 클래스를 상속해 설정을 할 수 있다. 인증 방식 설정 configure(AuthenticationManagerBuilder auth) 인증 방식과 관련된 설정을 하기 위한 메소드 AuthenticationManagerBuilder는 인증객체(AuthenticationManager)를 생성하기 위한 클래스이다. In Memory authentication나 UserDetailsService를 사용하는 다양한 인증 방식을 손 쉽게 구축할 수 있도록 지원한다. configure(AuthenticationManagerBuilder auth) private final CustomUserDetailsService customUserDetailsService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserDetailsService);}

0

Spring-JWT(JSON Web Token) - 4. JWT 다루기

4. JWT 다루기목차 Spring-JWT(JSON Web Token) - 4. JWT 다루기 Spring-JWT(JSON Web Token) - 3. Spring Security 적용하기 Spring-JWT(JSON Web Token) - 2. 회원가입 Spring-JWT(JSON Web Token) - 1. JWT 알아보기 JWT를 다루기 위한 Util Class만들기 JwtUtil 객체는 Jwts.builder를 이용해 JWT를 생성하고 Jwts.parserBuilder를 이용해 Token을 JWT로 변환시켜 데이터를 가져오도록 한다. Jwts.builder(JwtBuilder) setHeader JWT의 Header 에 대한 설정을 위한 메소드 setSubject, setExpiration, setIssuer, setAudience, setNotBefore, setIssuedAt Registed Payload는 각각에 해당하는 set 메소드들이 제공된다. setClaims JWT의 Claim 데이터 를 추가하기 위한 메소드 signWith Header와 Payload를 갖고 Secret Key 로 서명한다. 암호화 알고리즘으로는 보통 HMAC or RSA 알고리즘을 사용한다. Jwts.parserBuilder(JwtParser) setSigningKey 데이터 위변조 확인을 위해 secretKey를 이용해 JWS에 대한 유효성 검증을 한다. secretKey를 이용한 검증 실패시 해당 JWT는 사용하지 못한다. parseClaimsJws token을 JWS로 파싱해준다.

0

Spring-JWT(JSON Web Token) - 3. Spring Security 적용하기

3. 로그인목차 Spring-JWT(JSON Web Token) - 4. JWT 다루기 Spring-JWT(JSON Web Token) - 3. Spring Security 적용하기 Spring-JWT(JSON Web Token) - 2. 회원가입 Spring-JWT(JSON Web Token) - 1. JWT 알아보기 의존성 추가Spring Boot에 Security를 적용하기 위해 Spring Security 의존성과 JWT를 사용하기위해 jjwt 의존성을 추가해주도록 한다. build.gradle dependencies { .... implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' // https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1' ....} Security 설정하기Spring Security는 인증에 필요한 사용자 정보를 저장할 때 비밀번호는 PasswordEncoder 객체를 이용해 암호화된 Password로 저장돼야 한다. 현재 프로젝트에서는 PasswordEncoder를 구현한 BcryptPasswordEncoder 객체를 이용해 암호화를 할 것이다.

0

Spring-JWT(JSON Web Token) - 2. 회원가입

2. 회원가입목차 Spring-JWT(JSON Web Token) - 4. JWT 다루기 Spring-JWT(JSON Web Token) - 3. Spring Security 적용하기 Spring-JWT(JSON Web Token) - 2. 회원가입 Spring-JWT(JSON Web Token) - 1. JWT 알아보기 의존성 관계build.gradle dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test'} 회원가입을 위한 DTO 만들기SignUpRequest.java @Data@AllArgsConstructor@NoArgsConstructorpublic class SignUpRequest { private String username; private String password;}

0

Spring-JWT(JSON Web Token) - 1. JWT 알아보기

1. JWT(JSON Web Token) 알아보기목차 Spring-JWT(JSON Web Token) - 4. JWT 다루기 Spring-JWT(JSON Web Token) - 3. Spring Security 적용하기 Spring-JWT(JSON Web Token) - 2. 회원가입 Spring-JWT(JSON Web Token) - 1. JWT 알아보기 참고 https://jwt.io/ JWT 란? JWT는 JSON Web Token의 약자로 사용자 정보와 데이터 속성과 같은 Claim 정보를 JSON 을 이용해 표현한 Web TokenJWT는 Token내에 필요한 모든 정보를 가지고 전달해주는 자가수용적인 특징이 있다 JWT는 Header, Payload, Signature 세가지로 구성돼 있다. 각 부분은 Json 형태 로 이뤄져 있으며 base64로 인코딩 돼 .로 나뉘어 구분된다.

0

Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기

목차 Spring Security OAuth2 - Handler Spring Security OAuth2 - Login 페이지 Customizing 하기 Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기 Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기 Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기 Google OAuth2 인증 방식 이해하기 OAuth2를 이용한 로그인 구현 이해하기 2. Resource Server로부터 사용자 정보 가져오기Spring Security 설정하기OAuth2 인증을 마친 후에 Resource Server로부터 사용자 정보를 가져오기 위해서는 UserInfo EndPoint에 접근할 필요가 있다. HttpSecurity객체의 oauth2Login().userInfoEndpoint().userService() 메소드를 이용해서 UserInfo EndPoint로부터 사용자 정보를 가져올 Service를 등록한다. @EnableWebSecurity@RequiredArgsConstructorpublic class SecurityConfig extends WebSecurityConfigurerAdapter { private final CustomOAuth2UserService customOAuth2UserService; @Override protected void configure(HttpSecurity http) throws Exception { http .antMatcher("/**").authorizeRequests() .antMatchers("/").permitAll() .anyRequest().authenticated(); http .oauth2Login() .userInfoEndpoint() .userService(customOAuth2UserService); }} 스프링에서 기본적으로 제공하는 OAuth2ProviderGoogle, Facebook, Github 등을 통해 OAuth2인증하기 위한 기본적인 설정값들이 들어가 있다. 해당 정보를 통해 ClientRegistration 객체를 생성한다. authorizationUri 인증을 진행하기 위해 사용하는 URI tokenUri Resource server로부터 access token을 받기 위해 사용하는 URI jwkSetUri token의 유효성(서명)을 확인할 수 있는 public key(JSON Web Key)를 받을 수 있는 URI userInfoUri Resource Server(ex. Google)로부터 사용자 정보를 가져오기 위한 URI userNameAttributeName Resource server가 제공하는 id값 clientName Resource Server 이름(client Name을 사용할 때도 있다.)

0

Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기

목차 Spring Security OAuth2 - Handler Spring Security OAuth2 - Login 페이지 Customizing 하기 Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기 Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기 Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기 Google OAuth2 인증 방식 이해하기 OAuth2를 이용한 로그인 구현 이해하기 1. OAuth2를 이용한 인증 사용하기참고 https://www.docs4dev.com/docs/en/spring-security/5.1.2.RELEASE/reference/jc.html#oauth2client Google에 Web Application 등록하기Google의 OAuth2 서비스를 이용하기 위해서 사용할 Web Application을 등록해 Client Id와 Client Secret을 받아야 한다. 구글 클라우드 플랫폼 : https://console.cloud.google.com/ API및 서비스 > OAuth 동의 화면을 클릭

0

Google OAuth2 인증 방식 이해하기

목차 Spring Security OAuth2 - Handler Spring Security OAuth2 - Login 페이지 Customizing 하기 Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기 Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기 Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기 Google OAuth2 인증 방식 이해하기 OAuth2를 이용한 로그인 구현 이해하기 Google Oauth2 인증 시나리오 살펴보기 Web Server가 Google에 Access Token 을 요청한다. 사용자가 구글 ID와 Password를 이용해 로그인을 한다. Web Server쪽으로 Authorization code 가 반환된다. Authorization code를 이용해 Access Token을 요청 구글에서 Access Token값을 반환한다. Access Token을 이용해 사용자의 profile과 같은 정보들을 가져온다. 스프링에서 기본적으로 제공하는 OAuth2Provider https://docs.aws.amazon.com/ko_kr/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html Google, Facebook, Github 등을 통해 OAuth2인증하기 위한 기본적인 설정값들이 들어가 있다. authorizationUri 인증을 진행하기 위해 사용하는 URI tokenUri Resource server 로부터 Access token 을 받기 위해 사용하는 URI jwkSetUri Google로 부터 받은 JWT(JSON Web Token) 의 유효성을 확인할 수 있는 Public key(JSON Web Key) 를 받을 수 있는 URI userInfoUri Resource Server (ex. Google) 로부터 사용자 정보를 가져오기 위한 URI userNameAttributeName Resource server 가 제공하는 id값 clientName Resource Server 이름 (client Name을 사용할 때도 있다.) public enum CommonOAuth2Provider { GOOGLE { @Override public Builder getBuilder(String registrationId) { ClientRegistration.Builder builder = getBuilder(registrationId, ClientAuthenticationMethod.BASIC, DEFAULT_REDIRECT_URL); builder.scope("openid", "profile", "email"); builder.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth"); builder.tokenUri("https://www.googleapis.com/oauth2/v4/token"); builder.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs"); builder.issuerUri("https://accounts.google.com"); builder.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo"); builder.userNameAttributeName(IdTokenClaimNames.SUB); builder.clientName("Google"); return builder; } }, ... private static final String DEFAULT_REDIRECT_URL = "{baseUrl}/{action}/oauth2/code/{registrationId}"; protected final ClientRegistration.Builder getBuilder(String registrationId, ClientAuthenticationMethod method, String redirectUri) { ClientRegistration.Builder builder = ClientRegistration.withRegistrationId(registrationId); builder.clientAuthenticationMethod(method); builder.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE); builder.redirectUri(redirectUri); return builder; }}

0

OAuth2를 이용한 로그인 구현 이해하기

목차 Spring Security OAuth2 - Handler Spring Security OAuth2 - Login 페이지 Customizing 하기 Spring Security OAuth2를 이용한 로그인 구현 - 사용자 정보 가져오기 Spring Security OAuth2를 이용한 로그인 구현 - Spring boot OAuth2 인증 살펴보기 Spring Security OAuth2를 이용한 로그인 구현 - OAuth2를 이용한 인증 사용하기 Google OAuth2 인증 방식 이해하기 OAuth2를 이용한 로그인 구현 이해하기 OAuth2를 이용한 로그인 구현 이해하기OAuth란? OAuth란 Open Authorization의 약자이며 사용자 인증을 대신해서 해주고 Client에게 Access Token을 발급해 사용자 Resource에 대한 접근 권한(Authorization)을 제공하는 방법이다. OAuth가 등장하기 이전에는 각 사이트 별로 사용자 Id와 Password를 입력해 인증을 하고 정보를 저장하는 방식이였다. 때문에 사용자 입장에서는 본인의 Id와 Password를 각 사이트에 등록해야 한다는 신뢰성 적인 문제와 각 사이트에서는 사용자 정보를 관리하고 책임져야 하는 문제점이 있었다. 해당 문제를 해결하기 위해 등장한 방법이 OAuth 인증 방식이다. OAuth2 사용하기Web Application을 기준으로 OAuth2를 사용하기 위한 방법은 크게 3가지가 있다. Resource Server(Google, Naver 등) 에 Application을 등록 Resource Owner 사용자 인증을 통해 Autorization Code 를 가져오기 Client가 획득한 Autorization Code를 이용해 Access Token 을 발급 받기

0

Spring Security Form Login - 4. 회원가입 페이지 만들기

회원가입을 처리하기 위한 Controller 추가 요청으로 들어온 데이터를 받기 위한 DTO객체 생성 회원가입 page생성하기 회원 가입을 처리하기 위한 Controller 추가/signup으로 들어온 사용자 정보를 DTO객체로 받고 Account객체를 생성한 후 DB에 저장한다. @Controller@RequiredArgsConstructorpublic class SecurityController { private final CustomUserDetailsService customUserDetailsService; private final PasswordEncoder passwordEncoder; @GetMapping("/") public String index(){ return "index"; } @GetMapping("/login") public String login(){ return "login"; } @GetMapping("/logout") public void logout(){ } @GetMapping("/signup") public String signup(@ModelAttribute("signupDto") AccountDto accountDto, Model model){ return "signup"; } @PostMapping("/signup") public String createNewAccount(@ModelAttribute("signupDto") @Validated AccountDto accountDto, Model model){ Account account = Account.builder() .username(accountDto.getUsername()) .email(accountDto.getEmail()) .password(passwordEncoder.encode(accountDto.getPassword())) .role(Role.USER) .build(); customUserDetailsService.saveAccount(account); return "redirect:"; }} User정보를 받기위한 DTO만들기@Datapublic class AccountDto { private String username; private String email; private String password;} 회원가입 template 만들기<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Bootstrap Registration Page with Floating Labels</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="robots" content="noindex, nofollow"> <meta name="googlebot" content="noindex, nofollow"> <meta name="viewport" content="width=device-width, initial-scale=1"><!-- <link rel="stylesheet" type="text/css" href="/css/result-light.css">--> <script type="text/javascript" th:src="@{/js/dummy.js}"></script> <script type="text/javascript" th:src="@{/js/jquery.slim.min.js}"></script> <script type="text/javascript" th:src="@{/js/bootstrap.bundle.min.js}"></script> <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/> <link rel="stylesheet" th:href="@{/css/all.css}"/> <link rel="stylesheet" th:href="@{/css/style.css}"/> <link rel="stylesheet" type="text/css" th:href="@{/css/signup.css}"/> <script id="insert"></script></head><body><div class="container"> <div class="row"> <div class="col-lg-10 col-xl-9 mx-auto"> <div class="card card-signin flex-row my-5"> <div class="card-img-left d-none d-md-flex"> <!-- Background image for card set in CSS! --> </div> <div class="card-body"> <h5 class="card-title text-center">Register</h5> <form class="form-signin" th:object="${signupDto}" th:action="@{/signup}" th:method="post"> <div class="form-label-group"> <input th:field="*{username}" type="text" id="inputUserame" class="form-control" placeholder="Username" required autofocus> <label for="inputUserame">Username</label> </div> <div class="form-label-group"> <input th:field="*{email}" type="email" id="inputEmail" class="form-control" placeholder="Email address" required> <label for="inputEmail">Email address</label> </div> <hr> <div class="form-label-group"> <input th:field="*{password}" type="password" id="inputPassword" class="form-control" placeholder="Password" required> <label for="inputPassword">Password</label> </div> <div class="form-label-group"> <input type="password" id="inputConfirmPassword" class="form-control" placeholder="Password" required> <label for="inputConfirmPassword">Confirm password</label> </div> <button class="btn btn-lg btn-primary btn-block text-uppercase" type="submit">Register</button> </form> </div> </div> </div> </div></div><script type="text/javascript">//<![CDATA[//]]></script><script> // tell the embed parent frame the height of the content if (window.parent && window.parent.parent) { window.parent.parent.postMessage(["resultsFrame", { height: document.body.getBoundingClientRect().height, slug: "1nu8g6e5" }], "*") } // always overwrite window.name, in case users try to set it manually window.name = "result"</script></body></html> Form에서 기입된 데이터 보내기

0

Spring Security Form Login - 3. 템플릿 만들기

Spring에서 제공하는 Thymeleaf템플릿 엔진을 이용해 로그인 페이지를 구현했다. Form Login Page<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head> <title>Bootstrap Login Page Card with Floating Labels</title> <script type="text/javascript" th:src="@{/js/dummy.js}"></script> <script type="text/javascript" th:src="@{/js/jquery.slim.min.js}"></script> <script type="text/javascript" th:src="@{/js/bootstrap.bundle.min.js}"></script> <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}"/> <link rel="stylesheet" th:href="@{/css/all.css}"/> <link rel="stylesheet" th:href="@{/css/style.css}"/></head><body><div th:class="container"> <div class="row"> <div class="col-sm-9 col-md-7 col-lg-5 mx-auto"> <div class="card card-signin my-5"> <div class="card-body"> <h5 class="card-title text-center">Sign In</h5> <form class="form-signin" th:action="@{/login}" method="post"> <div class="form-label-group"> <input type="text" th:name="username" class="form-control" placeholder="Email address" required autofocus> <label th:for="username">Email address</label> </div> <div class="form-label-group"> <input type="password" th:name="password" class="form-control" placeholder="Password" required> <label th:for="password">Password</label> </div> <div class="custom-control custom-checkbox mb-3"> <input type="checkbox" class="custom-control-input" id="customCheck1"> <label class="custom-control-label" for="customCheck1">Remember password</label> </div> <button class="btn btn-lg btn-primary btn-block text-uppercase" type="submit">Sign in</button> </form> </div> </div> </div> </div></div></body></html> Form 로그인을 처리하는 url로 post요청을 보낸다. <form class="form-signin" th:action="@{/login}" method="post"> username과 password를 받는 input태그에서 name속성에 username과 password를 확실히 기입해줘야 Security가 해당 데이터를 얻어올 수 있다. <input type="text" th:name="username" class="form-control" placeholder="Email address" required autofocus>...<input type="password" th:name="password" class="form-control" placeholder="Password" required> 로그인 후 진입 화면<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"><head> <meta charset="UTF-8"> <title>Title</title></head><body><h1>시작페이지</h1><form action="/logout" th:action="@{/logout}" th:method="post" sec:authorize="isAuthenticated()"> <button type="submit" value="logout">로그 아웃</button></form></body></html>

0

Spring Security Form Login - 2. Security 설정 및 UserDetailsService 정의하기

로그인 로그아웃을 처리를 위한 Controller 생성 Spring Security 설정하기 UserDetailsService 구현하기 로그인 로그아웃을 처리를 위한 Controller/login으로 사용자 로그인 요청을 처리하고 /logout으로 사용자 로그아웃 요청을 처리한다. @Controller@RequiredArgsConstructorpublic class SecurityController { private final CustomUserDetailsService customUserDetailsService; private final PasswordEncoder passwordEncoder; @GetMapping("/") public String index(){ return "index"; } @GetMapping("/login") public String login(){ return "login"; } @GetMapping("/logout") public void logout(){ }} Spring Security 설정하기Spring Security를 설정하고 싶으면 EnableWebSecurity어노테이션과 WebSecurityConfigurerAdapter 클래스를 상속해 method들을 overriding한다. configure(AuthenticationManagerBuilder auth) AuthenticationManager를 설정하기 위해 사용하는 method configure(WebSecurity web) 전역적인 security를 설정할 때 사용하는 method, 보통은 보안 예외처리에 사용한다. configure(HttpSecurity http) request 단위로 보안을 걸때 사용하는 method configure(HttpSecurity http)을 이용해 허가를 하는 경우에는 Spring Filter Chain을 거처야 하지만 configure(WebSecurity web)를 이용하면 Spring Filter Chain을 거치지 않는다. @EnableWebSecurity@RequiredArgsConstructorpublic class SecurityConfig extends WebSecurityConfigurerAdapter { private final CustomUserDetailsService customUserDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserDetailsService); } @Override public void configure(WebSecurity web) throws Exception { web .ignoring() .antMatchers("/css/**", "/js/**") .antMatchers("/favicon.ico", "/resources/**", "/error") ; } @Override protected void configure(HttpSecurity http) throws Exception { http. authorizeRequests() .anyRequest().authenticated(); http .formLogin() // Form Login을 이용한 인증 방식을 사용 .loginPage("/login") // Login Page로 redirect할 경로를 적어준다. .defaultSuccessUrl("/", true) // 로그인 성공후 이동할 경로 .permitAll() ; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }}

0

Spring Security Form Login - 1. 기본적인 모델 정의하기

Spring properties 설정하기Spring Security에서 사용하는 기본적인 user정보를 등록한다. jpa를 사용하므로 관련 옵션도 추가해준다. application.ymlspring: security: user: name: user password: 1234 jpa: hibernate: ddl-auto: create-drop properties: hibernate: show_sql: true format_sql: true profiles: include: mysqllogging: level: org.springframework.security: DEBUG application-mysql.ymlspring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/{테이블명}?serverTimezone=UTC&characterEncoding=UTF-8 username: user_id password: user_password jpa: database: mysql database-platform: org.hibernate.dialect.MySQL5InnoDBDialect Entity 생성하기사용자 정보를 저장하기 위한 Account Entity를 만든다. @Entity@NoArgsConstructor@AllArgsConstructor@Getterpublic class Account { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long idx; private String username; @Column(unique = true, nullable = false) private String email; private String password; @Enumerated(EnumType.STRING) private Role role; private String getRoleValue(){ return this.role.getValue(); } @Builder public Account(String username, String email, String password, Role role){ this.username = username; this.email = email; this.password = password; this.role = role; }}