목차
프로젝트 만들기
application.properties
spring.application.name=sts15
spring.h2.console.path=/h2
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testDB
spring.datasource.username=sa
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
logging.level.com.gimhae.sts15.controller=debug
Dept.class
package com.gimhae.sts15.model.entity;
import com.gimhae.sts15.model.Deptvo;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
public class Dept {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int deptno;
String dname;
String loc;
public Deptvo toVo() {
return Deptvo.builder().deptno(deptno).dname(dname).loc(loc).build();
}
}
DeptVo.class
package com.gimhae.sts15.model;
import com.gimhae.sts15.model.entity.Dept;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Deptvo {
int deptno;
String dname;
String loc;
public Dept toEntity() {
return Dept.builder().deptno(deptno).dname(dname).loc(loc).build();
}
}
Users.class
package com.gimhae.sts15.model.entity;
import com.gimhae.sts15.model.UsersVo;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Users {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int num;
String email;
String pw;
String name;
public UsersVo toVo() {
return UsersVo.builder().num(num).email(email).pw(pw).name(name).build();
}
}
UsersVo.class
package com.gimhae.sts15.model;
import com.gimhae.sts15.model.entity.Users;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UsersVo {
int num;
String email,pw,name;
public Users toEntity() {
return Users.builder().num(num).email(email).pw(pw).name(name).build();
}
}
DeptRepo.Interface
package com.gimhae.sts15.model;
import org.springframework.data.repository.CrudRepository;
import com.gimhae.sts15.model.entity.Dept;
public interface DeptRepo extends CrudRepository<Dept, Integer> {
}
UsersRepo.Class
package com.gimhae.sts15.model;
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import com.gimhae.sts15.model.entity.Users;
public interface UsersRepo extends CrudRepository<Users, Integer> {
Optional<Users> findByEmailAndPw(String email,String pw);
}
ProjectApplication
package com.gimhae.sts15;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import com.gimhae.sts15.model.DeptRepo;
import com.gimhae.sts15.model.Deptvo;
import com.gimhae.sts15.model.UsersRepo;
import com.gimhae.sts15.model.UsersVo;
@SpringBootApplication
public class Sts15Application implements CommandLineRunner{
public static void main(String[] args) {
SpringApplication.run(Sts15Application.class, args);
}
@Autowired
UsersRepo usersRepo;
@Autowired
DeptRepo deptRepo;
@Override
public void run(String... args) throws Exception {
List<UsersVo> userList=List.of(
UsersVo.builder().email("user1@localhost").pw("1234").name("user1").build(),
UsersVo.builder().email("user2@localhost").pw("1234").name("user2").build()
);
userList.forEach(vo->usersRepo.save(vo.toEntity()));
// usersRepo.saveAll(()->userList.iterator());
List.of(
Deptvo.builder().dname("test1").loc("test").build(),
Deptvo.builder().dname("test2").loc("test").build(),
Deptvo.builder().dname("test3").loc("test").build(),
Deptvo.builder().dname("test4").loc("test").build()
).forEach(vo->deptRepo.save(vo.toEntity()));
}
}
DeptController
package com.gimhae.sts15.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.gimhae.sts15.model.DeptRepo;
import com.gimhae.sts15.model.Deptvo;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@RestController
@RequiredArgsConstructor
@RequestMapping("/dept/")
@CrossOrigin(origins = "http://localhost:3000",methods = {RequestMethod.GET,RequestMethod.POST})
@Slf4j
public class DeptController {
final DeptRepo deptRepo;
ResponseEntity resp=ResponseEntity.status(401).build();
@GetMapping("")
public ResponseEntity<?> list(HttpSession session) {
// log.debug(session.getAttribute("result").toString());
if(session.getAttribute("result")==null) return resp;
log.debug("login ok");
List<Object> list=new ArrayList<>();
deptRepo.findAll().forEach(entity->list.add(entity.toVo()));
return ResponseEntity.ok().body(list);
}
@PostMapping("")
public ResponseEntity<?> add(@RequestBody Deptvo bean,HttpSession session) {
if(session.getAttribute("result")==null) return resp;
deptRepo.save(bean.toEntity());
return ResponseEntity.ok().build();
}
@GetMapping("{deptno}")
public ResponseEntity<?> detail(@PathVariable int deptno,HttpSession session) {
if(session.getAttribute("result")==null) return resp;
deptRepo.findById(deptno).ifPresentOrElse(t->{
resp=ResponseEntity.ok().body(t.toVo());
}, ()->{
resp=ResponseEntity.badRequest().build();
});
return resp;
}
}
LoginController
package com.gimhae.sts15.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.gimhae.sts15.model.UsersRepo;
import com.gimhae.sts15.model.UsersVo;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RestController
@RequestMapping("/login/")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin(origins = "http://localhost:3000",methods = {RequestMethod.GET,RequestMethod.POST})
public class LoginController {
final UsersRepo usersRepo;
ResponseEntity<?> resp;
@PostMapping("")
public ResponseEntity<?> login(String id,String pw,HttpSession session) {
// log.debug("{1}:{2}".format(id, pw));
log.debug("id:"+id);
log.debug("pw:"+pw);
usersRepo.findByEmailAndPw(id, pw).ifPresentOrElse(entity->{
UsersVo bean=entity.toVo();
// resp=ResponseEntity.ok(bean);
resp=ResponseEntity.ok().body(bean);
session.setAttribute("result", true);
session.setAttribute("num", bean.getNum());
log.debug("로그인됨");
}, ()->{
resp=ResponseEntity.badRequest().build();
});
return resp;
}
@GetMapping("logout")
public ResponseEntity logout(HttpSession session) {
session.invalidate();
return ResponseEntity.ok().build();
}
}
LoginFilter
package com.gimhae.sts15;
import java.io.IOException;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@Component
public class LoginFilter implements Filter{
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("before filter...");
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Credentials", "true");
if(req.getRequestURI().startsWith("/dept")) {
HttpSession session=req.getSession();
if(session.getAttribute("result")!=null) {
chain.doFilter(request, response);
}else {
res.sendError(401);
}
}else {
chain.doFilter(request, response);
}
System.out.println("after filter...");
}
}
React 프로젝트 만들기
App.js
import logo from './logo.svg';
import './App.css';
import { BrowserRouter, Route, Router, Routes } from 'react-router-dom';
import Main from './pages/Main';
import Intro from './pages/Intro';
import Depts from './pages/Depts';
import Login from './pages/Login';
import { createContext, useState } from 'react';
import Logout from './pages/Logout';
import Dept from './pages/Dept';
export const LoginContext=createContext();
function App() {
const [login,setLogin]=useState(false);
return (
<LoginContext.Provider value={[login,setLogin]}>
<BrowserRouter>
<Routes>
<Route path='/' element={<Main/>}/>
<Route path='/intro' element={<Intro/>}/>
<Route path='/dept/' element={<Depts/>}/>
<Route path='/dept/:deptno' element={<Dept/>}/>
<Route path='/login/' element={<Login/>}/>
<Route path='/logout/' element={<Logout/>}/>
</Routes>
</BrowserRouter>
</LoginContext.Provider>
);
}
export default App;
Main.js
import React, { useContext } from 'react'
import { Link } from 'react-router-dom'
import { LoginContext } from '../App';
function Main() {
const [login,setLogin]=useContext(LoginContext);
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
{login?<Link to={'/logout'}>logout</Link>:<Link to={'/login'}>login</Link>}
</nav>
<div className='container'>
<h2>Index page</h2>
</div>
</>
)
}
export default Main
Intro.js
import React, { useContext } from 'react'
import { Link } from 'react-router-dom'
import { LoginContext } from '../App';
function Main() {
const [login,setLogin]=useContext(LoginContext);
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
{login?<Link to={'/logout'}>logout</Link>:<Link to={'/login'}>login</Link>}
</nav>
<div className='container'>
<h2>Index page</h2>
</div>
</>
)
}
export default Main
Depts.js
import React, { useEffect, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
function Depts() {
const navigate=useNavigate();
const [arr,setArr]=useState([]);
useEffect(()=>{
fetch('http://localhost:8080/dept/',{
method:'GET',
credentials:'include'
})
.then(res=>res.json())
.then(json=>setArr(json))
.catch(err=>{
console.log(err);
navigate('/login/');
})
},[]);
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
<Link to={'/login/'}>login</Link>
</nav>
<div className='container'>
<h2>list page</h2>
{arr.map(ele=>(
<Link to={'/dept/'+ele.deptno}>
<dl>
<dt>{ele.dname}</dt>
<dd>{ele.loc}</dd>
</dl>
</Link>
))}
</div>
</>
)
}
export default Depts
Dept.js
import React, { useEffect, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
function Dept() {
const navigate=useNavigate();
const {deptno}=useParams();
const [bean,setBean]=useState(null);
const [editable,setEditable]=useState(true);
useEffect(()=>{
fetch('http://localhost:8080/dept/'+deptno,{
method:'GET',
credentials:'include'
})
.then(res=>res.json()).then(json=>setBean(json)).catch(alert);
},[]);
const editAction=(e)=>{
e.preventDefault();
if(editable)
setEditable(!editable);
else
navigate('/dept/');
};
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
<Link to={'/login/'}>login</Link>
</nav>
<div className='container'>
<h2>{editable?'edit':'detail'} page</h2>
<form onSubmit={editAction}>
<div>
<input name='deptno' value={bean==null?'':bean.deptno} readOnly={true}/>
</div>
<div>
<input name='dname' value={bean==null?'':bean.dname}
onChange={e=>setBean({...bean,dname:e.target.value})} readOnly={editable}/>
</div>
<div>
<input name='loc' value={bean==null?'':bean.loc}
onChange={e=>setBean({...bean,loc:e.target.value})} readOnly={editable}/>
</div>
<div>
<button type='submit'>수정</button>
</div>
</form>
</div>
</>
)
}
export default Dept
Login.js
import React, { useContext, useRef } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { LoginContext } from '../App';
function Login() {
const [login,setLogin]=useContext(LoginContext);
const navigate=useNavigate();
const refId=useRef();
const refPw=useRef();
const loginAction=(e)=>{
console.log(`id=${refId.current.value}&pw=${refPw.current.value}`);
e.preventDefault();
fetch('http://localhost:8080/login/',{
method:'POST',
body:`id=${refId.current.value}&pw=${refPw.current.value}`,
credentials:'include',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res=>res.json())
.then(json=>{
setLogin(true);
navigate('/');
})
.catch(alert);
};
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
<Link to={'/login/'}>login</Link>
</nav>
<div className='container'>
<h2>login page</h2>
<form onSubmit={loginAction}>
<div>
<input ref={refId} name='id' placeholder='email'/>
</div>
<div>
<input ref={refPw} name='pw' placeholder='password'/>
</div>
<div>
<button>로그인</button>
</div>
</form>
</div>
</>
)
}
export default Login
Logout.js
import React, { useContext, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { LoginContext } from '../App';
function Logout() {
const [login,setLogin]=useContext(LoginContext);
useEffect(()=>{
fetch('http://localhost:8080/login/logout',{
method:'GET',
credentials:'include'
})
.then(res=>res.ok)
.catch(alert)
.finally(()=>{
setLogin(false);
});
},[]);
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
<Link to={'/login/'}>login</Link>
</nav>
<div className='container'>
<h2>logout page</h2>
<p>이용해주셔서 감사합니다</p>
</div>
</>
)
}
export default Logout
Oauth
jwt(표준규격모델) 토큰을 이용해 로그인을 관리한다.
https://jwt.io/libraries?language=Java
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
pom.xml
<dependency>
<groupId>oi.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<vresion>0.11.2</vresion>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
JwtService
package com.gimhae.sts15.service;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap.KeySetView;
import org.springframework.stereotype.Service;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
@Service
public class JwtService {
final Key key=Keys.secretKeyFor(SignatureAlgorithm.HS256);
public String createToken(String email) {
System.out.println(key.toString());
System.out.println(Base64.getEncoder().encode(key.getEncoded()));
String token=Jwts.builder()
.addClaims(Map.of("email",email))
.setExpiration(new Date(System.currentTimeMillis()+1000*100))
.signWith(key)
.compact();
return token;
}
public String getAuthEmail(String token) {
JwtParser parser=Jwts.parserBuilder()
.setSigningKey(key)
.build();
String email=(String) parser.parseClaimsJws(token).getBody().get("email");
return email;
}
}
Project Application
package com.gimhae.sts15;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import com.gimhae.sts15.model.DeptRepo;
import com.gimhae.sts15.model.Deptvo;
import com.gimhae.sts15.model.UsersRepo;
import com.gimhae.sts15.model.UsersVo;
import com.gimhae.sts15.service.JwtService;
@SpringBootApplication
public class Sts15Application implements CommandLineRunner{
public static void main(String[] args) {
SpringApplication.run(Sts15Application.class, args);
}
@Autowired
UsersRepo usersRepo;
@Autowired
DeptRepo deptRepo;
@Override
public void run(String... args) throws Exception {
List<UsersVo> userList=List.of(
UsersVo.builder().email("user1@localhost").pw("1234").name("user1").build(),
UsersVo.builder().email("user2@localhost").pw("1234").name("user2").build()
);
userList.forEach(vo->usersRepo.save(vo.toEntity()));
// usersRepo.saveAll(()->userList.iterator());
List.of(
Deptvo.builder().dname("test1").loc("test").build(),
Deptvo.builder().dname("test2").loc("test").build(),
Deptvo.builder().dname("test3").loc("test").build(),
Deptvo.builder().dname("test4").loc("test").build()
).forEach(vo->deptRepo.save(vo.toEntity()));
String token=jwtService.createToken("user1@localhost");
System.out.println("token:"+token);
String email=jwtService.getAuthEmail(token);
System.out.println("email:"+email);
}
@Autowired
JwtService jwtService;
}
LoginFilter
package com.gimhae.sts15;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Component;
import com.gimhae.sts15.model.UsersRepo;
import com.gimhae.sts15.model.entity.Users;
import com.gimhae.sts15.service.JwtService;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@Component
public class LoginFilter implements Filter{
@Autowired
JwtService jwtService;
@Autowired
UsersRepo usersRepo;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("before filter...");
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse res=(HttpServletResponse) response;
System.out.println(req.getRequestURI());
res.setHeader("Access-Control-Allow-Credentials", "true");
if(req.getRequestURI().startsWith("/dept")) {
// HttpSession session=req.getSession();
// if(session.getAttribute("result")!=null) {
// chain.doFilter(request, response);
// }else {
// res.sendError(401);
// }
try {
String token=req.getHeader("Authorization");
// if(!token.startsWith("Bearer ")) {
// throw new RuntimeException();
// }
System.out.println("test"+token);
token=token.split(" ")[1];
System.out.println("token:"+token);
String email=jwtService.getAuthEmail(token);
System.out.println("email:"+email);
Users user=usersRepo.findByEmail(email);
System.out.println("user:"+user);
chain.doFilter(request, response);
}catch(Exception e) {
res.sendError(401);
}
}else {
chain.doFilter(request, response);
}
System.out.println("after filter...");
}
}
LoginControl
package com.gimhae.sts15.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.gimhae.sts15.model.UsersRepo;
import com.gimhae.sts15.model.UsersVo;
import com.gimhae.sts15.service.JwtService;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RestController
@RequestMapping("/login/")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin(origins = "http://localhost:3000",methods = {RequestMethod.GET,RequestMethod.POST})
public class LoginController {
final UsersRepo usersRepo;
final JwtService jwtService;
ResponseEntity<?> resp;
@PostMapping("")
public ResponseEntity<?> login(String id,String pw,HttpSession session) {
log.debug("id:"+id);
log.debug("pw:"+pw);
usersRepo.findByEmailAndPw(id, pw).ifPresentOrElse(entity->{
UsersVo bean=entity.toVo();
String token=jwtService.createToken(id);
resp=ResponseEntity.ok().body(token);
log.debug("로그인됨");
}, ()->{
resp=ResponseEntity.badRequest().build();
});
return resp;
}
@GetMapping("logout")
public ResponseEntity logout(HttpSession session) {
session.invalidate();
return ResponseEntity.ok().build();
}
}
UsersRepo
package com.gimhae.sts15.model;
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import com.gimhae.sts15.model.entity.Users;
public interface UsersRepo extends CrudRepository<Users, Integer> {
Optional<Users> findByEmailAndPw(String email,String pw);
Users findByEmail(String email);
}
DeptControl
package com.gimhae.sts15.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.gimhae.sts15.model.DeptRepo;
import com.gimhae.sts15.model.Deptvo;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@RestController
@RequiredArgsConstructor
@RequestMapping("/dept/")
@CrossOrigin(origins = "http://localhost:3000",methods = {RequestMethod.GET,RequestMethod.POST})
@Slf4j
public class DeptController {
final DeptRepo deptRepo;
ResponseEntity resp=ResponseEntity.status(401).build();
@GetMapping("")
public ResponseEntity<?> list(HttpSession session) {
// log.debug(session.getAttribute("result").toString());
// if(session.getAttribute("result")==null) return resp;
log.debug("login ok");
List<Object> list=new ArrayList<>();
deptRepo.findAll().forEach(entity->list.add(entity.toVo()));
return ResponseEntity.ok().body(list);
}
@PostMapping("")
public ResponseEntity<?> add(@RequestBody Deptvo bean,HttpSession session) {
if(session.getAttribute("result")==null) return resp;
deptRepo.save(bean.toEntity());
return ResponseEntity.ok().build();
}
@GetMapping("{deptno}")
public ResponseEntity<?> detail(@PathVariable int deptno,HttpSession session) {
if(session.getAttribute("result")==null) return resp;
deptRepo.findById(deptno).ifPresentOrElse(t->{
resp=ResponseEntity.ok().body(t.toVo());
}, ()->{
resp=ResponseEntity.badRequest().build();
});
return resp;
}
}
Login.js
import React, { useContext, useRef } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { LoginContext } from '../App';
function Login() {
const [login,setLogin]=useContext(LoginContext);
const navigate=useNavigate();
const refId=useRef();
const refPw=useRef();
const loginAction=(e)=>{
console.log(`id=${refId.current.value}&pw=${refPw.current.value}`);
e.preventDefault();
fetch('http://localhost:8080/login/',{
method:'POST',
body:`id=${refId.current.value}&pw=${refPw.current.value}`,
credentials:'include',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res=>res.text())
.then(token=>{
console.log('login token:'+token);
setLogin('Bearer '+token);
navigate('/');
})
.catch(alert);
};
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
<Link to={'/login/'}>login</Link>
</nav>
<div className='container'>
<h2>login page</h2>
<form onSubmit={loginAction}>
<div>
<input ref={refId} name='id' placeholder='email'/>
</div>
<div>
<input ref={refPw} name='pw' placeholder='password'/>
</div>
<div>
<button>로그인</button>
</div>
</form>
</div>
</>
)
}
export default Login
Depts.js
import React, { useContext, useEffect, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { LoginContext } from '../App';
function Depts() {
const [login,setLogin]=useContext(LoginContext);
const navigate=useNavigate();
const [arr,setArr]=useState([]);
useEffect(()=>{
console.log(login);
//if(login==null) return navigate('/login/');
fetch('http://localhost:8080/dept/',{
method:'GET',
credentials:'include',
withCredentials:true,
headers:{
'Authorization':login,
'Content-Type':'application/json'
}
})
.then(res=>{res.json();
console.log('login then:'+login);})
.then(json=>setArr(json))
.catch(err=>{
console.log(err);
// navigate('/login/');
});
},[]);
return (
<>
<nav>
<Link to={'/'}>home</Link>{' '}
<Link to={'/intro'}>intro</Link>{' '}
<Link to={'/dept/'}>dept</Link>{' '}
<Link to={'/login/'}>login</Link>
</nav>
<div className='container'>
<h2>list page</h2>
{arr.map(ele=>(
<Link to={'/dept/'+ele.deptno}>
<dl>
<dt>{ele.dname}</dt>
<dd>{ele.loc}</dd>
</dl>
</Link>
))}
</div>
</>
)
}
export default Depts
App.js
import logo from './logo.svg';
import './App.css';
import { BrowserRouter, Route, Router, Routes } from 'react-router-dom';
import Main from './pages/Main';
import Intro from './pages/Intro';
import Depts from './pages/Depts';
import Login from './pages/Login';
import { createContext, useState } from 'react';
import Logout from './pages/Logout';
import Dept from './pages/Dept';
export const LoginContext=createContext();
function App() {
const [login,setLogin]=useState(null);
return (
<LoginContext.Provider value={[login,setLogin]}>
<BrowserRouter>
<Routes>
<Route path='/' element={<Main/>}/>
<Route path='/intro' element={<Intro/>}/>
<Route path='/dept/' element={<Depts/>}/>
<Route path='/dept/:deptno' element={<Dept/>}/>
<Route path='/login/' element={<Login/>}/>
<Route path='/logout/' element={<Logout/>}/>
</Routes>
</BrowserRouter>
</LoginContext.Provider>
);
}
export default App;
'100일 챌린지 > 빅데이터기반 인공지능 융합 서비스 개발자' 카테고리의 다른 글
Day 85 - Django 사용하기 (0) | 2024.11.28 |
---|---|
Day 85 - python database 연동하기 (1) mysql (1) | 2024.11.28 |
Day 79 - React로 CRUD 프로그램 만들기 (3) Nodejs API 서비스 이용 (0) | 2024.11.20 |
Day 78 - react 문법(2) (0) | 2024.11.20 |
Day 78 - React로 CRUD 프로그램 만들기 (2) spring에서 데이터셋 활용하기 [h2] (1) | 2024.11.19 |