Skip to content

Commit

Permalink
Merge pull request #75 from pknu-wap/feature/#74/display_user_connect…
Browse files Browse the repository at this point in the history
…ion_status

Feature/#74/display user connection status
  • Loading branch information
dohyeondol1 authored Sep 7, 2024
2 parents 47573a4 + 9adb4aa commit 5a45916
Show file tree
Hide file tree
Showing 25 changed files with 482 additions and 326 deletions.
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 54 additions & 0 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions client/src/component/minihome/friend.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ const FriendDetails = styled.div`
flex-direction: column;
`;

const Friendstatus = styled.div`
display: flex;
flex-direction: column;
`;

function Friend() {
const [totalMember, setTotalMember] = useState(null);
const [friends, setFriends] = useState([]);
Expand Down Expand Up @@ -121,6 +126,9 @@ function Friend() {
<div>{friend.name}</div>
<div>({friend.nickname})</div>
</FriendDetails>
<Friendstatus>
<div>{friend.state === 1 ? '온라인' : '오프라인'}</div>
</Friendstatus>
</FriendCard>
))
) : (
Expand Down
6 changes: 4 additions & 2 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ dependencies {
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'

//mariadb(선택)
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:2.7.4'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '3.4.1'

implementation 'javax.servlet:jstl'

Expand All @@ -33,7 +36,6 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'

implementation "org.apache.tomcat.embed:tomcat-embed-jasper"
implementation 'org.springframework.boot:spring-boot-starter-security'
}

tasks.named('test') {
Expand Down
1 change: 0 additions & 1 deletion server/src/main/java/com/my/kde_db/KdeDbApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ public static void main(String[] args) {

}

//확인 url 주소: http://localhost:8080/user/create?id=userid&pw=password&nick=nickname&address=address&g=gender
52 changes: 52 additions & 0 deletions server/src/main/java/com/my/kde_db/config/CustomLogoutHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.my.kde_db.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
@Component
public class CustomLogoutHandler implements LogoutHandler {

private final HttpSession session;
private final String kakaoLogoutUrl = "https://kapi.kakao.com/v1/user/logout";

@Autowired
public CustomLogoutHandler(HttpSession session) {
this.session = session;
}

@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
String accessToken = (String) session.getAttribute("accessToken");
if (authentication != null && accessToken != null) {

// 카카오 로그아웃 API 호출
try {
URL url = new URL(kakaoLogoutUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
int responseCode = conn.getResponseCode(); // API 호출

if (responseCode == HttpURLConnection.HTTP_OK) {
System.out.println("카카오 로그아웃 성공");
} else {
System.out.println("카카오 로그아웃 실패, 응답 코드: " + responseCode);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}



59 changes: 59 additions & 0 deletions server/src/main/java/com/my/kde_db/config/CustomUserDetails.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.my.kde_db.config;

import com.my.kde_db.vo.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.Collections;

public class CustomUserDetails implements UserDetails {

private final User user;

public CustomUserDetails(User user) {
this.user = user;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// 모든 사용자에게 동일한 권한 부여
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
}

@Override
public String getPassword() {
return user.getPassword(); // 사용자 비밀번호
}

@Override
public String getUsername() {
return user.getId(); // 사용자 아이디
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}

public User getUser() {
return user;
}
}

84 changes: 80 additions & 4 deletions server/src/main/java/com/my/kde_db/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,93 @@
package com.my.kde_db.config;

import com.my.kde_db.service.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private CustomLogoutHandler customLogoutHandler;
@Autowired
private CustomUserDetailsService customUserDetailsService;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and() // CORS 설정 추가
.csrf().disable() // CSRF 보호 비활성화
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.cors().configurationSource(request -> {
var corsConfig = new CorsConfiguration();
corsConfig.setAllowedOrigins(List.of("http://localhost:3000", "https://miniwapp.netlify.app"));
corsConfig.setAllowedMethods(List.of("*"));
corsConfig.setAllowedHeaders(List.of("*"));
corsConfig.setAllowCredentials(true);
return corsConfig;
})
.and()
.csrf().disable()
.authorizeRequests()
.anyRequest().permitAll(); // 모든 경로를 인증 없이 접근 가능하도록 설정
.antMatchers("/user/login", "/user/create", "/user/logout", "/user/status", "/login**", "/error**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint((request, response, authException) -> {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
})
.and()
.formLogin()
.loginProcessingUrl("/user/login")
.successHandler((request, response, authentication) -> {
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
request.getSession().setAttribute("me", userDetails.getUser());
response.sendRedirect("/user/loginSuccess");
})
.failureHandler((request, response, exception) -> {
response.sendRedirect("/user/loginFailure");
})
.and()
.oauth2Login()
.successHandler((request, response, authentication) -> {
response.sendRedirect("https://miniwapp.netlify.app/redirection/success");
})
.failureHandler((request, response, exception) -> {
exception.printStackTrace();
response.sendRedirect("https://miniwapp.netlify.app/redirection/fail");
})
.and()
.logout()
.logoutUrl("/logout")
.addLogoutHandler(customLogoutHandler)
.logoutSuccessUrl("/user/logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
}
28 changes: 0 additions & 28 deletions server/src/main/java/com/my/kde_db/config/WebConfig.java

This file was deleted.

Loading

0 comments on commit 5a45916

Please sign in to comment.