20221103 --> 이어서
@Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/user/**") .authenticated() // /user/** 은 인증 필요 --> 아무 사용자 인증만 되면 들어갈 수 있다.
.antMatchers("/manager/**").access("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
//manager는 ROLE_MANAGER권한을 가진자만 접근가능
//manager는 ROLE_ADMIN 권한을 가진자도 접근가능
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
//manager는 ROLE_ADMIN권한을 가진자만 접근가능
.and()
.formLogin()
.loginPage("/loginForm")
.loginProcessingUrl("/login")
.failureUrl("/loginFail")
.defaultSuccessUrl("/");
return http.build();
}
▶user로 로그인하면 user에만 접속 가능
manager로 로그인하면 user와 manager에 접속가능
admin으로 접속하면 user manager admin 모두 접속가능
▶SecurityConfig에서 @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)//특정주소 접근시 권한 및 인가
이게 걸려있어서
SecurityController02 에서 @Secured("ROLE_MANAGER") 걸수 있음
@Secured("ROLE_MANAGER")
//count 계정
@GetMapping("/count")
public String count() {
System.out.println("SecurityController02 user start . . . . . ");
return "count";
}
//들어가기전에 ROLE_MANAGER인지 ROLE_ADMIN인지 검증함
@PreAuthorize("hasRole('ROLE_MANAGER')or hasRole('ROLE_ADMIN') ")
@GetMapping("/count/2")
public String count2() {
System.out.println("SecurityController02 admin2 start . . . . . ");
return "count2";
}
<h1>count 인증성공</h1>
서버단만 만듬
REST(REpresentational State Transfer)란, "웹에 존재하는 모든 자원(이미지, 동영상, DB 자원)에 고유한 URI를 부여해
활용"하는 것으로, 자원을 정의하고 자원에 대한 주소를 지정하는 방법론을 의미
Postman-win64-7.36.1-Setup 설치
-->C:\Java Programming\301Class Tools 여기에 있음 끌고오기
package com.oracle.oBootJpaApi01.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Data
@SequenceGenerator(
name = "member_seq_gen5",
sequenceName = "member_seq_generator5",
initialValue = 1,
allocationSize = 1
)
@Table(name = "member5")
public class Member {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "member_seq_gen5"
)
@Column(name = "member_id")
private Long id;
@Column(name = "userName")
private String name;
private Long sal;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team; // join
}
package com.oracle.oBootJpaApi01.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Data
@SequenceGenerator(
name = "team_seq_gen5",
sequenceName = "team_seq_generator5",
initialValue = 1,
allocationSize = 1
)
@Table(name = "team5")
public class Team {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "team_seq_gen5")
private Long teamId;
@Column(name = "teamname", length = 50)
private String name;
}
package com.oracle.oBootJpaApi01.repository;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.oracle.oBootJpaApi01.domain.Member;
@Repository
public interface MemberRepository {
Long savae(Member member);
List<Member> findAll();
}
package com.oracle.oBootJpaApi01.repository;
import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.stereotype.Repository;
import com.oracle.oBootJpaApi01.domain.Member;
import lombok.RequiredArgsConstructor;
@Repository
@RequiredArgsConstructor //private이기떄문에 생성자 만들어주기
public class JpaMemberRepository implements MemberRepository {
private final EntityManager em;
@Override
public Long savae(Member member) {
System.out.println("JpaMemberRepository savae before . . . . . . . ");
em.persist(member);
return member.getId(); //pk키 만 전달
}
@Override
public List<Member> findAll() {
List<Member> memberList = em.createQuery("select m from Member m ", Member.class)
.getResultList(); //list로 돌려줘야함
return memberList;
}
}
package com.oracle.oBootJpaApi01.service;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.oracle.oBootJpaApi01.domain.Member;
import com.oracle.oBootJpaApi01.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
@Transactional
public class MemberService {
private final MemberRepository memberRepository;
//전체회원조회
public List<Member> getListAllMember(){
List<Member> listMember = memberRepository.findAll();
return listMember ;
}
}
필요없는 내용까지도 전부다 조회가 됨 --> 해킹되기 쉬움
package com.oracle.oBootJpaApi01.controller;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.oracle.oBootJpaApi01.domain.Member;
import com.oracle.oBootJpaApi01.service.MemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
//Controller + ResponseBody
//사용목적 --> Ajax + RestApi
@RestController
@RequiredArgsConstructor
@Slf4j
public class JpaRestApiController {
private final MemberService memberService;
//Bad Api //버전
@GetMapping("/restApi/v1/members")
public List<Member> membersVer1(){
System.out.println("JpaRestApiController //restApi/v1/members start. . . ");
List<Member> listMember = memberService.getListAllMember();
return listMember;
}
}
▶JSON 으로 출력됨 배열구조로 나옴
▶전부다 조회되기때문에Bad Api
//목표: 이름 & 급여만 전송
//Good Api
//목표: 이름 & 급여만 전송
@GetMapping("/restApi/v2/members")
public Result membersVer21() {
List<Member> findMembers = memberService.getListAllMember();
log.info("/restApi/v21/members findMembers.size()-->"+findMembers.size());
//MemberRtnDto를 생성해주기
List<MemberRtnDto> resultList = new ArrayList<MemberRtnDto>();
//List<Member> findMembers를 -->List<MemberRtnDto> resultList 이전
//이전목적 : 반드시 필요한 Data 만 보여준다(외부 노출 최대한 금지 )
for(Member member : findMembers ) { //생성자를 통해서 이전
MemberRtnDto memberRtnDto = new MemberRtnDto(member.getName() , member.getSal() );
resultList.add(memberRtnDto);
}
return new Result(resultList.size(),resultList);
// T는 인스턴스를 생성할 때 구체적인 타입으로 변경 -->유연성
@Data
@AllArgsConstructor
class Result<T> { //리절드 객체를 생성할때 T타입으로 생성됨 (감싸줌)
private final int totCount; //총인원수 추가
private final T data ;
}
@Data
@AllArgsConstructor
class MemberRtnDto { //이름하고 급여만 돌려주기 위해서 두개 생성.
private String name ;
private Long sal;
}
람다는 매개변수 화살표(->) 함수몸체로 이용하여 사용 할 수 있습니다.
//목표: 이름 & 급여만 전송
@GetMapping("/restApi/v22/members")
public Result membersVer22() {
List<Member> findMembers = memberService.getListAllMember();
log.info("/restApi/v22/members findMembers.size()-->"+findMembers.size());
// 자바 8에서 추가한 스트림(Streams)은 람다를 활용할 수 있는 기술 중 하나
List<MemberRtnDto> memberCollect = findMembers.stream()
.map(m->new MemberRtnDto(m.getName(),m.getSal()))
.collect(Collectors.toList())
;
log.info("/restApi/v22/members memberCollect.size()-->"+memberCollect.size());
return new Result(memberCollect.size(),memberCollect);
}
@RestController
@RequiredArgsConstructor
@Slf4j
public class JpaRestApiController {
private final MemberService memberService;
@PostMapping("/restApi/v1/memberSave")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) {
Long id = memberService.saveMember(member)
return new CreateMemberResponse(id);
}
@Data
@RequiredArgsConstructor
class CreateMemberResponse{
private final Long id;
// public CreateMemberResponse(Long id) {
// this.id = id;
// }
}
//회원가입 API
public Long saveMember(@Valid Member member) {
System.out.println("MemberService join member.getName()->"+member.getName());
Long id = memberRepository.save(member);
return id;
}
▶크로으로안나오고 postman에서 해줘야함