스프링부트+jsp로 배달사이트 만들기-27 관리자 가게상세/AOP

2021. 12. 17. 00:29스프링부트

관리자상세.zip
0.01MB

압축파일의 관리자 상세페이지 jsp, js, css를 붙여습니다

store폴더의 storeDetail.jsp는 관리자페이지도 같이 사용하기 위해 수정본으로 새로 준비했습니다

 

 

 

가게 상세 페이지

storeDetail.js의 다음 부분을 수정합니다

 

 

지난 장에서 DB에서 내 가게를 등록했었는데 등록한 가게 외에는 접근할 수 없게 막아야합니다 

남의 가게의 정보를 수정할 수 없어야 하니까요

 

인터셉터나 AOP를 사용할 수 있겠지만 컨트롤러의 파라미터를 체크하기 위해 AOP를 사용하겠습니다

 

pom.xml에 추가합니다

		<!-- AOP -->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

 

스프링부트 메인메서드에 @EnableAspectJAutoProxy를 붙여줍니다

@EnableAspectJAutoProxy
@SpringBootApplication
public class BaeminApplication {

	public static void main(String[] args) {
		SpringApplication.run(BaeminApplication.class, args);
	}

}

 

AOP는 어노테이션, 접근제어자, 메서드이름 등등.. 특정 패턴에 의해 실행될 메서드를 지정할 수 있는데 특정 어노테이션에 의해 실행 될수 있게 구현하려고 합니다

 

AOP패키지를 만들고 어노테이션을 생성합니다

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IsMyStore {

}

내 가게인지 체크한다는 의미로 isMyStore라고 지었습니다

 

 

AOP패키지에 AdminAOP클래스를 생성합니다

@Aspect
@Component
public class AdminAOP {


	
	
}

AOP클래스로 사용하겠다고 @Aspect를 붙여줍니다
@Component를 붙여 빈으로 등록합니다

 

 

@Around("@annotation(com.baemin.aop.IsMyStore)")
public Object myStore(ProceedingJoinPoint j) throws Throwable   {

return null;
}

@Around는 ProceedingJoinPoint객체의 proceed()메서드를 기준으로 컨트롤러 메서드의 앞 뒤에 실행될 코드를 작성합니다

 

("@annotation(com.baemin.aop.IsMyStore)")는 com.baemin.aop에 IsMyStore라는 어노테이션이 붙은 메서드에서 실행하겠다는 의미입니다
 
ProceedingJoinPoint객체로 해당 메서드의 각종 정보들을 얻을 수 있습니다
검사할 가게 번호는 메서드의 첫번째 파라미터에 넣어야 된다는 규칙을 정하고 메서드의 첫번째 파라미터만 검사하겠습니다
@Around("@annotation(com.baemin.aop.IsMyStore)")
public Object myStore(ProceedingJoinPoint j) throws Throwable   {
	long storeId = 0;
	Object[] args = j.getArgs();
	if(args.length > 0) {
		Object arg = args[0];
		
		if(arg instanceof Long) {
			storeId = (long) arg;
		} else if(arg instanceof Store) {
			storeId = ((Store) arg).getId();
		} else if(arg instanceof Food) {
			storeId = ((Food) arg).getStoreId();
		} 
	}
	if(!isMyStore(storeId)) { 
		System.out.println("aop 에러");
		return new ResponseEntity<Object>(HttpStatus.UNAUTHORIZED);
	}
	Object returnObj = j.proceed();
	return returnObj;
}

ProceedingJoinPoint객체의 Args()로 메서드의 파라미터를 가져옵니다

파라미터의 첫번째 값인 args[0]을 체크하고 isMyStore() 메서드를 실행해 내 계정에 등록된 가게인지 검사 후 통과한다면 j.proceed()를 반환해 해당 페이지에 접근할 수 있게합니다

 

@Autowired
private AdminService adminService;
public boolean isMyStore(long storeId) throws IOException {
	ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
	HttpSession session = attr.getRequest().getSession();
	List<Long> storeIdList = (List<Long>) session.getAttribute("myStore");
	
	if(storeIdList == null) {
		SecurityContext sc = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
		LoginService user = (LoginService) sc.getAuthentication().getPrincipal();
		long userId = user.getUser().getId();
		storeIdList = adminService.getMyStoreId(userId);
        	session.setAttribute("myStore", storeIdList);
	} 
	
	if(storeIdList.size() == 0) {
		return false;
	} else {
		if(storeIdList.contains(storeId)) {
			return true;
		} else {
			return false;
		}
	}
}

세션에 등록된 mystore 리스트를 가져옵니다

null이라면 시큐리티 세션의 계정의 id로 db에서 select해 세션에 저장합니다

 

adminService와 dao에 getMyStoreId()를 추가합니다

 

adminServiceImp

@Override
	public List<Long> getMyStoreId(long userId) {
		return adminDAO.getMyStoreId(userId);
	}

 

adminDAOImp

@Override
public List<Long> getMyStoreId(long userId) {
	return sql.selectList("admin.getMyStoreId", userId);
}

 

adminMapper

<select id="getMyStoreId" resultType="long">
	SELECT STORE_ID FROM BM_MY_STORE WHERE USER_ID = #{userId } 
</select>

 

컨트롤러의 검사하고 싶은 메서드에 @IsMyStore를 붙여줍니다

@IsMyStore
@GetMapping("/admin/management/detail/{id}") 
public String detail(@PathVariable long id, @AuthenticationPrincipal LoginService user, Model model) {
	long userId = user.getUser().getId();
	StoreDetail storeDetail = storeService.storeDetail(id, userId);
	model.addAttribute("store", storeDetail);
	model.addAttribute("adminPage", true);
	
	return "admin/detail";
}

 

 

계정에 등록된 가게일때

 

계정에 등록되지 않은 가게일때