반응형

 

@PreAuthorize()는 메서드를 실행하기 전에 하는 권한 검사

@PostAuthorize()는 메서드를 실행하고 클라이언트에게 응답을 하기 직전에 하는 권한 검사

 

<예시>

@PreAuthorize("isAuthenticated()")

 

인자로 올 수 있는 값...

  • hasRole([role]) : 현재 사용자의 권한이 파라미터의 권한과 동일한 경우 true
@PreAuthorize("hasRole('ADMIN') or hasRole('MANAGER')")

 

  • hasAnyRole([role1,role2]) : 현재 사용자의 권한이 파라미터의 권한 중 일치하는 것이 있는 경우 true
@PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")

 

  • principal : 사용자를 증명하는 주요객체(User)를 직접 접근할 수 있다.
  • authentication : SecurityContext에 있는 authentication 객체에 접근 할 수 있다.
@PreAuthorize("#userId == authentication.principal.id")
or
@PreAuthorize("#username == authentication.name")

 

  • permitAll() : 모든 접근 허용
  • denyAll() : 모든 접근 비허용
  • isAnonymous() : 현재 사용자가 익명(비로그인)인 상태인 경우 true
  • isRememberMe() : 현재 사용자가 RememberMe 사용자라면 true
  • isAuthenticated() : 현재 사용자가 익명이 아니라면 (로그인 상태라면) true
  • isFullyAuthenticated() : 현재 사용자가 익명이거나 RememberMe 사용자가 아니라면 true
@PreAuthorize("isAuthenticated()")
@PreAuthorize("isAnonymous()")

 

 

반응형
반응형

 

1. template/hello.html

데이터를 받아들일 html템플릿을 만들어둔다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello</title>
</head>
<body>
    <p th:text="${user}">Hello Thymeleaf!!</p>
</body>
</html>

 

2.Controller.java

자료를 넘길때는 ModelAndView객체에 담아서 보낸다.

...
	
@GetMapping("/user")
public ModelAndView hello(@RequestParam("id") String id) throws Exception {

    ModelAndView mav = new ModelAndView();		
    UserDto res = userService.getUserById(id);

    mav.setViewName("hello");	
    mav.addObject("user",res.getName());

    return mav;
}
    
 ...
반응형
반응형

 

 

1. Controller: UserProfileController.java

package com.example.myba.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.example.myba.dto.ItemDto;
import com.example.myba.dto.ResponseDto;
import com.example.myba.service.QuickService;

import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.extern.slf4j.Slf4j;

@RestController
@Slf4j
public class UserProfileController {
	
	@Autowired
	private QuickService quickService; //자동으로 값을 넣은 객체를 생성해줌. DI
	
	@GetMapping("/dummy")
	public String dummy() {
//		log.info("dummy");
		return "{}";
	}
	
	@GetMapping("/dummy2")
	public String dummy2() {
		return "dummy2";
	}
	
	@GetMapping("/member")
	public String getMember(@RequestParam("empNo") String empNo) {
		return "OK";
	}

	@GetMapping("/company/{id}")
	public String getCompany(@PathVariable("id") String id) {
		return "OK";	
	}
	
	@PostMapping("/item")
	public ResponseDto registerItem(@RequestBody ItemDto item) {
		
		boolean b = quickService.registerItem(item);
		
		if(b==true) {
			ResponseDto responseDto = new ResponseDto();
			responseDto.setMessage("ok");
			
			return responseDto;
		}
		
		ResponseDto responseDto = new ResponseDto();
		responseDto.setMessage("fail");
		
		return responseDto;
	}
	
	@PostMapping("/user")
	public String registerUser(@RequestBody String user) {		
		return "OK";
	}
	
	@GetMapping("/item")
	public ItemDto getItem(@RequestParam("id") String id) {
		ItemDto res = quickService.getItemById(id);
		return res;
	}
	
}

 

2. dto

- ItemDto.java

package com.example.myba.dto;

public class ItemDto {
	
	private String id;
	
	private String name;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
}

 

 

- ResponseDto.java

package com.example.myba.dto;

public class ResponseDto {
	private String message;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
	
}

 

3. mapper: QuickMapper.java

package com.example.myba.mapper;

import java.util.HashMap;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface QuickMapper {
	HashMap<String, Object> findById(HashMap<String, Object> paramMap);
}

 

 

 

4. mapper.xml: QuickMapper.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper 
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.example.myba.mapper.QuickMapper">

	<select id="findById" parameterType="hashmap" resultType="hashmap">
		SELECT id, name FROM item WHERE id = #{id}
	</select>
	
</mapper>

 

 

5. service: QuickService.java

package com.example.myba.service;

import java.util.HashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.myba.dto.ItemDto;
import com.example.myba.mapper.QuickMapper;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class QuickService {
	
	@Autowired QuickMapper quickMapper;
	
	public boolean registerItem(ItemDto itemDto) {
		// TODO:
		
		return true;
	}
	
	public ItemDto getItemById(String id) {
		
		HashMap<String, Object> paramMap = new HashMap<>();
		paramMap.put("id", id);
		
		HashMap<String, Object> res = quickMapper.findById(paramMap);
		
		
		ItemDto itemDto = new ItemDto();
		itemDto.setId((String)res.get("ID"));;
		itemDto.setName((String)res.get("NAME"));
		
		return itemDto;
	}
}

 

6. application.properties

spring.application.name=myba

#spring.datasource.url=jdbc:mysql://localhost:3306/personal_info
#spring.datasource.username=asdf
#spring.datasource.password=1234
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:~/test
spring.datasource.username=asdf
spring.datasource.password=1234

spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@12.34.56.78:1526:abcde
spring.datasource.username=asdf
spring.datasource.password=1234


mybatis.type-aliases-package=com.example.myba.mapper 
# Mybatis mapper 위치 설정
mybatis.mapper-locations= mybatis-mapper/*.xml

 

 

7. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.2.4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>myba</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>myba</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>3.0.3</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter-test</artifactId>
			<version>3.0.3</version>
			<scope>test</scope>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
		<dependency>
		    <groupId>org.springdoc</groupId>
		    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
		    <version>2.1.0</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		<dependency>
		    <groupId>org.projectlombok</groupId>
		    <artifactId>lombok</artifactId>
		    <version>1.18.30</version>
		    <scope>provided</scope>
		</dependency>
		
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
		</dependency>


	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

 

 

 

 

반응형
반응형

여기서 최신버전을 복사해서 pom.xml의 디펜던시에 넣어준다.

 

Maven Repository: org.springdoc » springdoc-openapi-starter-webmvc-ui » 2.5.0 (mvnrepository.com)

<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.5.0</version>
</dependency>

 

localhost:8080/swagger-ui/index.html

 

반응형
반응형

1. SpringDataJpaMemberRepository 인터페이스 작성

이번엔 클래스가 아닌 인터페이스를 만들어줍니다. 인터페이스만 만들면 객체는 JPA 템플릿이 자동으로 생성해준다고 합니다.

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface SpringDataJpaMemberRepository extends JpaRepository<Member, Long>, MemberRepository {

    @Override
    Optional<Member> findByName(String name);

}

통 CRUD 가 아닌 findByName만 구현하면 끝남.;;

 

2. SpringConfig 수정

SpringConfig에 등록된 repository들은 모두 삭제 또는 주석 처리하고, MemberRepository를 인젝션 받으면 됩니다.

 

package hello.hellospring;

import hello.hellospring.repository.MemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    private final MemberRepository memberRepository;

    @Autowired
    public SpringConfig(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Bean
    public MemberService memberService(){

        return new MemberService(memberRepository);
    }

}

 

SpringDataJpa방식은 이렇게 너무도 단순하지만, 이것만 익힐 경우 내부 처리방식등을 모르게 되어 유지보수를 못하게 되므로, 맹신하면 안된다고 하니 유념하시기 바랍니다.

 

~~끝~~

반응형
반응형

1. build.gradle dependencies 설정

기존 jdbc 라이브러리 대신 jpa라이브러리를 설정합니다. 설정 뒤에는 코끼리 아이콘을 클릭하여 라이브러리를 끌어와 설치해줍니다.

2. application.properties 설정

spring.jpa,.show-sql=true 는 jpa가 수행하는 sql을 볼 수 있도록 하는 옵션이고,

spring.jpa.hibernate.ddl-auto=none 은 회원 객체를 확인할 때 테이블을 자동 생성하는 기능은 끄고 시작하는 것입니다. 이번 예제에서는 테이블을 생성해 놓았으므로 none으로 합니다. none대신 create로 할 경우 테이블 생성까지도 자동으로 해 줍니다. 

 

3. Member 클래스 코드 수정

@Entity : JPA가 관리하는 Entity임을 인식시켜줌

@Id: PK를 인식시켜줌

@GeneratedValue: 자동 생성되는 값임을 인식시켜줌

package hello.hellospring.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Member {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4. JpmMemberRepository 클래스 구성

JPQL이라는 문법으로 Query를 작성합니다.

package hello.hellospring.repository;

import hello.hellospring.domain.Member;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;

public class JpaMemberRepository implements MemberRepository{

    private final EntityManager em; // 스프링 부트가 자동 생성함. 데이터 소스를 들고있음.

    public JpaMemberRepository(EntityManager em) {
        this.em = em;
    }


    @Override
    public Member save(Member member) {
        em.persist(member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        Member member = em.find(Member.class, id);
        return Optional.ofNullable(member);
    }

    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = em.createQuery("select m from Member m where m.name=:name", Member.class)
                .setParameter("name", name)
                .getResultList();

        return result.stream().findAny();

    }

    @Override
    public List<Member> findAll() {
        return em.createQuery("select m from Member m", Member.class)
            .getResultList();
    }
}

5. MemberService 클래스 수정

클래스 선언부 앞에 @Transactional 이라는 annotation을 붙여줍니다. 

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Transactional
public class MemberService {

    private final MemberRepository memberRepository;


    public MemberService(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }

    /*
    회원 가입 이하 생략
    */
   

6. SpringConfig 수정

위에서 구축한 JpaMemberRepository를 등록해줍니다.

package hello.hellospring;

import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.JpaMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

@Configuration
public class SpringConfig {

    private EntityManager em;

    @Autowired
    public SpringConfig(EntityManager em){
        this.em = em;
    }

//    private DataSource dataSource;
//
//    @Autowired
//    public SpringConfig(DataSource dataSource){
//        this.dataSource = dataSource;
//    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        //return new MemoryMemberRepository();
        //return new JdbcTemplateMemberRepository(dataSource);
        return new JpaMemberRepository(em);
    }
}

테스트코드는 수정 없이 사용 가능하므로 생략하겠습니다.

 

~~끝~~

반응형
반응형

1. 기존 MemberServiceTest크래스를 복사하여 MemberServiceIntegrationTest 클래스를 생성 후 아래와 같이 코드를 작성합니다. 

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {

    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;

    @Test
    void 회원가입() {
        //given
        Member member = new Member();
        member.setName("hello");

        //when
        Long saveId = memberService.join(member);

        //then
        Member findMember = memberService.findOne(saveId).get();
        assertThat(member.getName()).isEqualTo(findMember.getName());
    }

    @Test
    public void 중복_회원_예외(){
        //given
        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");

        //when
        memberService.join(member1);
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));

        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");

        //then


    }

}

2. H2 데이터베이스에 기존 작성한 spring 네임이 존재할 경우 에러가 나니, 데이터베이스 현황을 확인 후 테스트하시기 바랍니다.

 

반응형
반응형

1. build.gradle 설정파일로 가서 아래와 같이 코드를 추가해줍니다.

 

2. application.properties 파일에 가서 아래와 같이 수정해줍니다.

 

3. JdbcTemplateMemberRepository 클래스를 추가해줍니다.

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class JdbcTemplateMemberRepository implements MemberRepository{

    private final JdbcTemplate jdbcTemplate;

    //Datasource 자동으로 인젝션
    @Autowired  // 생성자가 1개일 경우 @Autowired는 생략 가능
    public JdbcTemplateMemberRepository(DataSource dataSource){
        jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public Member save(Member member) {
        SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
        jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("name", member.getName());

        Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
        member.setId(key.longValue());
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        List<Member> result = jdbcTemplate.query("select * from member where id = ?",memberRowMapper(), id);
        return result.stream().findAny();
    }

    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = jdbcTemplate.query("select * from member where name = ?",memberRowMapper(), name);
        return result.stream().findAny();
    }

    @Override
    public List<Member> findAll() {
        return jdbcTemplate.query("select * from member where name = ?",memberRowMapper());
    }

    private RowMapper<Member> memberRowMapper(){
        return (rs, rowNum) -> {

            Member member = new Member();
            member.setId(rs.getLong("id"));
            member.setName(rs.getString("name"));
            return member;
        };
    }
}

4. SpringConfig클래스 수정(조립)

SpringConfig클래스에서 MemberRepository의 인자로 JdbcTemplateMemberRepository를 넘겨줍니다.

package hello.hellospring;

import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class SpringConfig {

    private DataSource dataSource;

    @Autowired
    public SpringConfig(DataSource dataSource){
        this.dataSource = dataSource;
    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        //return new MemoryMemberRepository();
        return new JdbcTemplateMemberRepository(dataSource);
    }
}

 

순수 JDBC로 하는 것보다 중복코드를 줄여주어 훨씬 간단히 작성할 수 있다고 합니다. 

 

~~ 끝 ~~

 

반응형

+ Recent posts