JAVA Developer Training
38. Spring (상품,멤버를 이용한 sellerController) 본문
1. jwtUtil (토큰 관련 기능)
package com.example.jwt;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.springframework.stereotype.Service;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
// 토큰발행 (만료시간) , 토큰의 유효성 검사, 토큰과 관련된 메소드
@Service
public class JwtUtil {
// 토큰 생성용 보안키
private final String SECRETKEY = "fekjkfe43jfe";
// 정보 추출용 메소드
private <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = Jwts.parser().setSigningKey(SECRETKEY).parseClaimsJws(token).getBody();
return claimsResolver.apply(claims);
}
// 토큰 생성(아이디 정보를 이용한 토큰 생성)
public String generateToken(String username) {
// 2021-09-30 09:47:50.034 => 1234567890 => 1234567890123
// long tokenValidTime = 1000 * 60 * 30; //30분
long tokenValidTime = 1000 * 60 * 60 * 4; // 4시간
Map<String, Object> claims = new HashMap<>();
String token = Jwts.builder().setClaims(claims).setSubject(username)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + tokenValidTime))
.signWith(SignatureAlgorithm.HS256, SECRETKEY).compact();
return token;
}
// 토큰 유효성 확인
// vue에서 오는 토큰에서 꺼낸 아이디 정보와
// 시큐리티 세션에 보관되어 있던 아이디 정보
public Boolean validateToken(String token, String userid) {
// 토큰에서 아이디 정보 추출
final String username = this.extractUsername(token);
if (username.equals(userid) && !isTokenExpired(token)) {
return true;
}
return false;
}
// 토큰에서 아이디 정보 추출하기
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
// 토큰에서 만료 시간 추출하기
public Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
// 토큰의 만료시간이 유효한지 확인
public Boolean isTokenExpired(String token) {
// 만료시간 가져와서 현재시간보다 이전인지 확인
return this.extractExpiration(token).before(new Date());
}
}
2.jwtRequestFilter 인증서가 유효하면 컨트롤러로 진입
package com.example.jwt;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.example.service.MemberDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
//nodejs checkToken
//인증서가 유효하면 컨트롤러로 진입함
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
JwtUtil jwtUtil;
@Autowired
MemberDetailsService mService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
// 넘어오는것이 request
// const headers = {"Content-Type" : "application/json" ,"token" : 'aaaa'}
String token = request.getHeader("token");
// 임시
String username = null;
if (token != null) {
// 실제토큰
username = jwtUtil.extractUsername(token);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// 시큐리티에 로그인 처리루틴
UserDetails userDetails = mService.loadUserByUsername(username);
if (jwtUtil.validateToken(token, userDetails.getUsername())) {
UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(userDetails,
null, userDetails.getAuthorities());
upat.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(upat);
}
}
// 토큰 유무와 관련없이 컨트롤러로 넘겨
// 컨트롤러로 넘어가는 시점
// next (req,res)
filterChain.doFilter(request, response);
} catch (Exception e) {
response.sendError(578, "토큰오류");
}
}
}
3. 권한 설정 SecurityConfig
package com.example.security;
import com.example.jwt.JwtRequestFilter;
import com.example.service.MemberDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//새로운 기능을 추가한 DetailsService사용
@Autowired
MemberDetailsService mService;
//환경설정에서 객체만들기
//회원가입시 암호방식을 로그인시 같은 방식으로 적용해야 하기 때문에
@Bean
public BCryptPasswordEncoder encode(){
return new BCryptPasswordEncoder();
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
//인증박식은 MemberDetailsService를 사용하고, 암호화방식은
//위에만든 @Bean객체 방식으로 사용
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(mService).passwordEncoder(encode());
}
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
//권한 추가
http.authorizeRequests().antMatchers("/admin","/admin/*").hasAnyRole("ADMIN").anyRequest().permitAll();
//필터 추가
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
//session 저장방법
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//h2-console 사용
//127.0.0.1:8080/REST/h2-console
http.csrf().disable();
http.headers().frameOptions().sameOrigin();
}
}
4.SellorController
package com.example.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.example.entity.Item;
import com.example.entity.Member;
import com.example.jwt.JwtUtil;
import com.example.service.ItemServiceImpl;
import com.example.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/api")
public class SellerController {
@Autowired
MemberService mService;
@Autowired
ItemServiceImpl iService;
@Autowired
JwtUtil jwtUtil;
// 127.0.0.1:8080/REST/api/seller/item_delete
// [{"name":"a", "content":"b", "price":"c","quantity":"d"},{},{},{}....]
@RequestMapping(value = "/seller/item_delete", method = {
RequestMethod.DELETE }, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
// @ModelAttribute List<Item> list = 한번에 해결하는방법
public Map<String, Object> itemDeletePOST(@RequestBody List<Item> list, @RequestHeader("token") String token) {
Map<String, Object> map = new HashMap<>();
try {
// 판매자 이메일 가져오기
String email = jwtUtil.extractUsername(token);
for (Item item : list) {
Member member = mService.getMemberOne(email);
item.setMember(member);
}
iService.deleteBatch(list);
map.put("status", 200);
} catch (Exception e) {
map.put("status", e.hashCode());
}
return map;
}
// 127.0.0.1:8080/REST/api/seller/item_update
// [{"name":"a", "content":"b", "price":"c","quantity":"d"},{},{},{}....]
@RequestMapping(value = "/seller/item_update", method = {
RequestMethod.PUT }, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
// @ModelAttribute List<Item> list = 한번에 해결하는방법
public Map<String, Object> itemUpdatePUT(@RequestBody List<Item> list, @RequestHeader("token") String token) {
Map<String, Object> map = new HashMap<>();
try {
// 판매자 이메일 가져오기
String email = jwtUtil.extractUsername(token);
for (Item item : list) {
Member member = mService.getMemberOne(email);
item.setMember(member);
}
iService.updateBatch(list);
map.put("status", 200);
} catch (Exception e) {
map.put("status", e.hashCode());
}
return map;
}
// 127.0.0.1:8080/REST/api/seller/item_insert
// [{"name":"a", "content":"b", "price":"c","quantity":"d"},{},{},{}....]
@RequestMapping(value = "/seller/item_insert", method = {
RequestMethod.POST }, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
// @ModelAttribute List<Item> list = 한번에 해결하는방법
public Map<String, Object> itemInsertPost(@RequestParam("name") String[] name,
@RequestParam("content") String[] content, @RequestParam("price") Long[] price,
@RequestParam("quantity") Long[] quantity,
@RequestHeader("token") String token) {
Map<String, Object> map = new HashMap<>();
try {
// 판매자 이메일 가져오기
String email = jwtUtil.extractUsername(token);
// 위에서 받은 값을 list로 변환
List<Item> list = new ArrayList<Item>();
for (int i = 0; i < name.length; i++) {
Item item = new Item();
item.setName(name[i]);
item.setContent(content[i]);
item.setPrice(price[i]);
item.setQuantity(quantity[i]);
Member member = mService.getMemberOne(email);
item.setMember(member);
list.add(item);
}
// 일괄추가
iService.insertBatch2(list);
map.put("status", 200);
} catch (Exception e) {
map.put("status", e.hashCode());
}
return map;
}
// 127.0.0.1:8080/REST/api/seller/item_insert
// [{"name":"a", "content":"b", "price":"c","quantity":"d"},{},{},{}....]
@RequestMapping(value = "/seller/item_insert1", method = {
RequestMethod.POST }, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
// @ModelAttribute List<Item> list = 한번에 해결하는방법
public Map<String, Object> itemInsert1Post(@RequestBody List<Item> list, @RequestHeader("token") String token) {
Map<String, Object> map = new HashMap<>();
try {
// 판매자 이메일 가져오기
String email = jwtUtil.extractUsername(token);
for (Item item : list) {
Member member = mService.getMemberOne(email);
item.setMember(member);
}
iService.insertBatch2(list);
map.put("status", 200);
} catch (Exception e) {
map.put("status", e.hashCode());
}
return map;
}
// 127.0.0.1:8080/REST/api/seller/item_select
@RequestMapping(value = "/seller/item_select", method = {
RequestMethod.GET }, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, Object> itemSelectGET(@RequestParam("no") Long no) {
Map<String, Object> map = new HashMap<>();
try {
Item item = iService.selectItemOne(no);
map.put("status", 200);
map.put("item", item);
} catch (Exception e) {
map.put("status", e.hashCode());
}
return map;
}
// 127.0.0.1:8080/REST/api/seller/item_select_list
@RequestMapping(value = "/seller/item_select_list", method = {
RequestMethod.GET }, consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, Object> itemSelectListGET() {
Map<String, Object> map = new HashMap<>();
try {
List<Item> item = iService.selectItemList();
map.put("status", 200);
map.put("item", item);
} catch (Exception e) {
map.put("status", e.hashCode());
}
return map;
}
}
'트레이닝' 카테고리의 다른 글
40. Spring ( 게시판 과정 정리 - 환경설정 - 1) (0) | 2021.10.08 |
---|---|
39. Spring ( scheduler,interceptor ) (0) | 2021.10.08 |
37. Spring (아이템,상품 등록) (0) | 2021.10.06 |
36. Spring (멤버 등록) (0) | 2021.10.06 |
35. Spring ( 게시글 이전글, 다음글, 조회수 ) -2 (0) | 2021.09.29 |