SpringBootプロジェクトジェネレータ



CodeView


:
機能(一時)
  • 登録
  • 掲示板
  • プロジェクトの作成



    こうぞう



    コード#コード#

    Spring Securityを使用してログインを実装し、教室でのログインではありません.Spring Security:スプリングベースのアプリケーション・セキュリティ・フレームワーク
    ユーザー認証、権限、セキュリティ処理は簡単ですが、強力です.

    auth


    ✔️ MyUserDetail

    package codebook.codeview.auth;
    
    import codebook.codeview.entity.User;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    //import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import java.util.Collection;
    import java.util.Collections;
    
    public class MyUserDetail implements UserDetails {
        private String email;
        private String password;
        private String auth;
    
        public MyUserDetail(User user) {
            this.email = user.getEmail();
            this.password = user.getPassword();
            this.auth = "ROLE_" + user.getRole();
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return Collections.singletonList(new SimpleGrantedAuthority(this.auth));
        }
    
        @Override
        public String getPassword() {
            return this.password;
        }
    
        @Override
        public String getUsername() {
            return this.email;
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    }

    ✔️ SecurityConfig

    package codebook.codeview.auth;
    
    import codebook.codeview.service.UserService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    
    @EnableWebSecurity        //spring security 를 적용한다는 Annotation
    @RequiredArgsConstructor
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        private final UserService exService;
        /**
         * 규칙 설정
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/welcome").hasRole("USER")
                    .antMatchers("/signup").anonymous()
                    .and()
                    .formLogin()
                    .and()
                    .csrf().disable();		//로그인 창
        }
    
        /**
         * 로그인 인증 처리 메소드
         * @param auth
         * @throws Exception
         */
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(exService).passwordEncoder(new BCryptPasswordEncoder());
        }
    }

    controller


    ✔️ UserController

    package codebook.codeview.controller;
    
    import codebook.codeview.auth.MyUserDetail;
    import codebook.codeview.entity.User;
    import codebook.codeview.service.UserService;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.security.core.Authentication;
    //import org.springframework.security.core.userdetails.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PostMapping;
    
    import javax.servlet.ServletException;
    import java.io.IOException;
    
    @Controller
    @RequiredArgsConstructor
    @Slf4j
    public class UserController {
        private final UserService service;
    
        /**
         * 회원가입 폼
         * @return
         */
        @GetMapping("/signup")
        public String signupForm() {
            return "signup";
        }
    
        /**
         * 회원가입 진행
         * @param user
         * @return
         */
        @PostMapping("/signup")
        public String signup(User user) {
            user.setRole("USER");
            service.joinUser(user);
            return "redirect:/check";
        }
    
    //    @PostMapping("/signUp")
    //    public String signUp(User user) {
    //        user.setRole("USER");
    //        service.joinUser(user);
    //        return "redirect:/check";
    //    }
    
        /**
         * 유저 페이지
         * @param model
         * @param authentication
         * @return
         */
        @GetMapping("/")
        public String userAccess(Model model, Authentication authentication) {
            //Authentication 객체를 통해 유저 정보를 가져올 수 있다.
            MyUserDetail userDetail = (MyUserDetail)authentication.getPrincipal();  //userDetail 객체를 가져옴
            model.addAttribute("info", userDetail.getUsername());      //유저 이메일
            return "welcome";
        }
    }

    entity


    ✔️ User

    package codebook.codeview.entity;
    
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    @Getter
    @Setter
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String email;    //이메일
        private String password; //패스워드
        private String role;     //권한
    }

    repository


    ✔️ UserRepository

    package codebook.codeview.repository;
    
    import codebook.codeview.entity.User;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Repository;
    
    import javax.persistence.EntityManager;
    import javax.persistence.TypedQuery;
    
    @Repository
    @RequiredArgsConstructor
    public class UserRepository {
        private final EntityManager em;
    
        public void saveUser(User user){
            em.persist(user);
        }
    
        public User findUserByEmail(String email){
            TypedQuery<User> query = em.createQuery("select m from User as m where m.email = ?1", User.class)
                    .setParameter(1, email);
            return query.getSingleResult();
        }
    }

    service


    ✔️ UserService

    package codebook.codeview.service;
    
    import codebook.codeview.auth.MyUserDetail;
    import codebook.codeview.entity.User;
    import codebook.codeview.repository.UserRepository;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    //import org.springframework.security.core.userdetails.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.stereotype.Service;
    
    import javax.transaction.Transactional;
    
    @Service
    @RequiredArgsConstructor
    @Slf4j
    public class UserService implements UserDetailsService {
    
    //    @Autowired
        private final UserRepository repository;
    
        @Transactional
        public void joinUser(User user){
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            repository.saveUser(user);
        }
    
        @Override
        public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
            //여기서 받은 유저 패스워드와 비교하여 로그인 인증
            User user = repository.findUserByEmail(email);
            return new MyUserDetail(user);
        }
    
    }

    resources/templates


    ✔️ check.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>TEST!!!!!!!!</title>
    </head>
    <body>
    TEST!!!!!!!!!!!
    </body>
    </html>

    ✔️ signup.html

    <!--회원가입 페이지-->
    <!--signup.html-->
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    <form method="post" action="/signup">
        email : <input type="email" name="email">
        password : <input type="password" name="password">
        <button>회원가입</button>
    </form>
    </body>
    </html>

    ✔️ welcome.html

    <!--유저 페이지-->
    <!--user_access.html-->
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
        <meta charset="UTF-8">
        <title>user access</title>
    </head>
    <body>
    <span>환영합니다</span>
    <p th:text="${info}"></p>
    </body>
    </html>

    ✔️ resources/application.yml

    spring:
      datasource:
        driver-class-name: org.h2.Driver
        url: jdbc:h2:tcp://localhost/~/codeview
        username: sa
        password:
    
      jpa:
        hibernate:
          #옵션 create, update, none, create-drop, validate 있음
          ddl-auto: none
        properties:
          hibernate:
            format_sql: true
    
    logging:
      level:
        org:hibernate:SQL: DEBUG

    ✔️ build.gradle

    plugins {
    	id 'org.springframework.boot' version '2.5.5'
    	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    	id 'java'
    }
    
    group = 'codebook'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '11'
    
    configurations {
    	compileOnly {
    		extendsFrom annotationProcessor
    	}
    }
    
    repositories {
    	mavenCentral()
    }
    
    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'
    	runtimeOnly 'com.h2database:h2'
    //	compileOnly 'com.h2database:h2'
    	annotationProcessor 'org.projectlombok:lombok'
    	testImplementation 'org.springframework.boot:spring-boot-starter-test'
    }
    
    test {
    	useJUnitPlatform()
    }

    H2


    h 2をsqlの参照として使用する

    実行


    http://localhost:8080/ランタイムエラー

    Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

    http://localhost:8080/signup



    登録エラー

    SQL Error: 23502, SQLState: 23502
    
    NULL not allowed for column "ID"; SQL statement:
    insert into user (id, email, password, role) values (null, ?, ?, ?) [23502-200]
    
    Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
    SQL設定をH 2に変更し、いくつかのプレゼンテーションを追加したテーブルが作成されましたが、解決されませんでした.
    今日はミスを解決できなかった.
    残念:
    mavenではなくgradeを使用してプロジェクトを作成します.
    MySQLではなくH 2を使用します.
    Spring Securityはよくわかりません
    安全上の注意