JWT x SpringSecurity
β’
build.gradle
β’
νμκ°μ
λ° λ‘κ·ΈμΈ
β¦
Users.java
β¦
UserAuth.java
β¦
UserMapper.xml
β¦
UserMapper.java
β¦
UserServicejava
β¦
UserServiceImpl.java
β’
μΈμ¦
β¦
JWT ν ν° μΈμ¦
βͺ
SecurityConstants.java
βͺ
AuthenticationRequest.java
βͺ
JwtProps.java
βͺ
SecurityConfig.java
βͺ
CustomUser.java
βͺ
CustomUserDetailService.java
β¦
ν ν° Provider
βͺ
JwtTokenProvider.java
β’
ν ν° μμ±
β’
ν ν° ν΄μ
β’
ν ν° μ ν¨μ± κ²μ¬
β¦
νν° μ€μ
βͺ
JWT ν ν° μμ² νν°
β’
JwtRequestFilter.java
βͺ
JWT ν ν° μΈμ¦ νν°
β’
JwtAuthenticationFilter.java
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '2.7.18'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.aloha'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
// spring-boot-configuration-processor
implementation 'org.springframework.boot:spring-boot-configuration-processor'
// jwt
implementation 'io.jsonwebtoken:jjwt-api:0.12.3'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.3'
}
tasks.named('test') {
useJUnitPlatform()
}
Markdown
볡μ¬
νμκ°μ λ° λ‘κ·ΈμΈ
β’
Users.java
β’
UserAuth.java
β’
UserMapper.xml
β’
UserMapper.java
β’
UserServicejava
β’
UserServiceImpl.java
Users.java
@Data
public class Users {
private int no;
private String userId;
private String userPw;
private String userPwCheck; // λΉλ°λ²νΈ νμΈ
private String name;
private String email;
private Date regDate;
private Date updDate;
private int enabled; // ν΄λ©΄μ¬λΆ
// κΆν λͺ©λ‘
List<UserAuth> authList;
public Users() {
}
public Users(Users user) {
this.no = user.getNo();
this.userId = user.getUserId();
this.userPw = user.getUserPw();
this.name = user.getName();
this.email = user.getEmail();
this.authList = user.getAuthList();
}
}
Java
볡μ¬
UserAuth.java
// νμ κΆν
@Data
public class UserAuth {
private int authNo;
private String userId;
private String auth;
public UserAuth() {
}
public UserAuth(String userId, String auth) {
this.userId = userId;
this.auth = auth;
}
}
Java
볡μ¬
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aloha.jwt_security.mapper.UserMapper">
<!-- Users 맀ν-->
<resultMap type="Users" id="userMap">
<id property="no" column="no" />
<result property="no" column="no" />
<result property="userId" column="user_id" />
<result property="userPw" column="user_pw" />
<result property="name" column="name" />
<result property="email" column="email" />
<result property="enabled" column="enabled" />
<result property="regDate" column="reg_date" />
<result property="updDate" column="upd_date" />
<collection property="authList" resultMap="authMap"></collection>
</resultMap>
<!-- UserAuth 맀ν -->
<resultMap type="UserAuth" id="authMap">
<result property="userId" column="user_id" />
<result property="auth" column="auth" />
</resultMap>
<!-- νμ λ±λ‘ -->
<insert id="insert">
INSERT INTO user( user_id, user_pw, name, email )
VALUES ( #{userId}, #{userPw}, #{name} ,#{email} )
</insert>
<!-- νμ μ‘°ν -->
<select id="select" resultType="Users">
SELECT *
FROM user
WHERE no = #{no}
</select>
<!-- νμ μ‘°ν - id -->
<select id="login" resultMap="userMap">
SELECT u.no
,u.user_id
,user_pw
,name
,email
,enabled
,reg_date
,upd_date
,auth
FROM user u LEFT OUTER JOIN user_auth auth
ON u.user_id = auth.user_id
WHERE u.user_id = #{userId}
</select>
<!-- νμ κΆν λ±λ‘ -->
<insert id="insertAuth">
INSERT INTO user_auth( user_id, auth )
VALUES ( #{userId}, #{auth} )
</insert>
<!-- νμ μμ -->
<update id="update">
UPDATE user
SET user_id = #{userId}
,user_pw = #{userPw}
,name = #{name}
,email = #{email}
WHERE user_id = #{userId}
</update>
<!-- νμ μμ -->
<delete id="delete">
DELETE FROM user
WHERE user_id = #{userId}
</delete>
</mapper>
XML
볡μ¬
UserMapper.java
@Mapper
public interface UserMapper {
// νμ λ±λ‘
public int insert(Users user) throws Exception;
// νμ μ‘°ν
public Users select(int userNo) throws Exception;
// μ¬μ©μ μΈμ¦(λ‘κ·ΈμΈ) - id
public Users login(String username);
// νμ κΆν λ±λ‘
public int insertAuth(UserAuth userAuth) throws Exception;
// νμ μμ
public int update(Users user) throws Exception;
// νμ μμ
public int delete(String userId) throws Exception;
}
Java
볡μ¬
UserServicejava
public interface UserService {
// νμ λ±λ‘
public int insert(Users user) throws Exception;
// νμ μ‘°ν
public Users select(int userNo) throws Exception;
// λ‘κ·ΈμΈ
public void login(Users user, HttpServletRequest requset) throws Exception;
// νμ μμ
public int update(Users user) throws Exception;
// νμ μμ
public int delete(String userId) throws Exception;
}
Java
볡μ¬
UserServiceImpl.java
@Slf4j
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public int insert(Users user) throws Exception {
// λΉλ°λ²νΈ μνΈν
String userPw = user.getUserPw();
String encodedPw = passwordEncoder.encode(userPw);
user.setUserPw(encodedPw);
// νμ λ±λ‘
int result = userMapper.insert(user);
// κΆν λ±λ‘
if( result > 0 ) {
UserAuth userAuth = new UserAuth();
userAuth.setUserId( user.getUserId() );
userAuth.setAuth("ROLE_USER"); // κΈ°λ³Έ κΆν : μ¬μ©μ κΆν (ROLE_USER)
result = userMapper.insertAuth(userAuth);
}
return result;
}
@Override
public Users select(int userNo) throws Exception {
return userMapper.select(userNo);
}
@Override
public void login(Users user, HttpServletRequest requset) throws Exception {
String username = user.getUserId();
String password = user.getUserPwCheck();
log.info("username : " + username);
log.info("password : " + password);
// μμ΄λ, ν¨μ€μλ μΈμ¦ ν ν° μμ±
UsernamePasswordAuthenticationToken token
= new UsernamePasswordAuthenticationToken(username, password);
// ν ν°μ μμ²μ 보λ₯Ό λ±λ‘
token.setDetails( new WebAuthenticationDetails(requset) );
// ν ν°μ μ΄μ©νμ¬ μΈμ¦(λ‘κ·ΈμΈ)
Authentication authentication = authenticationManager.authenticate(token);
User authUser = (User) authentication.getPrincipal();
log.info("μΈμ¦λ μ¬μ©μ μμ΄λ : " + authUser.getUsername());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
@Override
public int update(Users user) throws Exception {
// λΉλ°λ²νΈ μνΈν
String userPw = user.getUserPw();
String encodedPw = passwordEncoder.encode(userPw);
user.setUserPw(encodedPw);
int result = userMapper.update(user);
return result;
}
@Override
public int delete(String userId) throws Exception {
int result = userMapper.delete(userId);
return result;
}
}
Java
볡μ¬
μΈμ¦
JWT ν ν° μΈμ¦
β’
SecurityConstants.java
β’
AuthenticationRequest.java
β’
JwtProps.java
β’
SecurityConfig.java
β’
CustomUser.java
β’
CustomUserDetailService.java
SecurityConstants.java
public final class SecurityConstants {
// π λ‘κ·ΈμΈ κ²½λ‘
public static final String AUTH_LOGIN_URL = "/login";
// π« μΈμ¦ μμ² ν€λ
// Authorization : "Bearer " + π(JWT)
public static final String TOKEN_HEADER = "Authorization";
public static final String TOKEN_PREFIX = "Bearer ";
public static final String TOKEN_TYPE = "JWT";
}
Java
볡μ¬
AuthenticationRequest.java
@Getter
@Setter
@ToString
public class AuthenticationRequest {
private String username;
private String password;
}
Java
볡μ¬
JwtProps.java
@Data
@Component
@ConfigurationProperties("com.aloha.jwt") // com.aloha.jwt κ²½λ‘ νμ μμ±λ€μ μ§μ
public class JwtProps {
// com.aloha.jwt.secretKeyλ‘ μ§μ λ νλ‘νΌν° κ°μ μ£Όμ
λ°λ νλ
// β
com.aloha.jwt.secret-key β‘ secretKey : {μΈμ½λ©λ μν¬λ¦Ώ ν€}
private String secretKey;
}
Java
볡μ¬
SecurityConfig.java
@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) //μ΄λ
Έν
μ΄μ
μ prePostEnabled = trueλ₯Ό μΆκ°νλ©΄ AuthenticationManagerλ₯Ό μλμΌλ‘ ꡬμ±ν©λλ€.
public class SecurityConfig {
@Autowired
private CustomUserDetailService customUserDetailService;
@Autowired
private JwtTokenProvider jwtTokenProvider;
private AuthenticationManager authenticationManager;
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
return authenticationManager;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
log.info("securityFilterChain...");
// νΌ κΈ°λ° λ‘κ·ΈμΈ λΉνμ±ν
http.formLogin( login -> login.disable() );
// HTTP κΈ°λ³Έ μΈμ¦ λΉνμ±ν
http.httpBasic( basic -> basic.disable() );
// CSRF(Cross-Site Request Forgery) 곡격 λ°©μ΄ κΈ°λ₯ λΉνμ±ν
http.csrf( csrf -> csrf.disable() );
// νν° μ€μ
// β
JWT μμ² νν° 1οΈβ£
// β
JWT μΈμ¦ νν° 2οΈβ£
http.addFilterAt(new JwtAuthenticationFilter(authenticationManager, jwtTokenProvider), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JwtRequestFilter(authenticationManager, jwtTokenProvider), UsernamePasswordAuthenticationFilter.class)
;
// μΈκ° μ€μ
http.authorizeHttpRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/user/**").hasAnyRole("USER" , "ADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")
// .anyRequest().authenticated()
;
// μ¬μ©μ μ 보λ₯Ό λΆλ¬μ€λ μλΉμ€ μ€μ
http.userDetailsService(customUserDetailService);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Java
볡μ¬
CustomUser.java
@Getter
@ToString
public class CustomUser implements UserDetails {
private Users user;
public CustomUser(Users user) {
this.user = user;
}
/**
* π’π‘π΄ κΆν getter λ©μλ
* β
UserDetails λ₯Ό CustomUser λ‘ κ΅¬ννμ¬,
* Spring Security μ User λμ μ¬μ©μ μ μ μΈμ¦ κ°μ²΄(CustomUser)λ₯Ό μ¬μ©νλ€λ©΄,
* κΆνμ 'ROLE_' λΆμ¬μ μ¬μ©ν΄μΌνλ€.
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getAuthList().stream()
.map( (auth) -> new SimpleGrantedAuthority(auth.getAuth()))
.collect(Collectors.toList());
}
@Override
public String getPassword() {
return user.getUserPw();
}
@Override
public String getUsername() {
return user.getUserId();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return user.getEnabled() == 0 ? false : true;
}
}
Java
볡μ¬
CustomUserDetailService.java
@Slf4j
@Service
public class CustomUserDetailService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) {
log.info("login - loadUserByUsername : " + username);
// MyBatisλ₯Ό μ¬μ©νμ¬ λ°μ΄ν°λ² μ΄μ€μμ μ¬μ©μ μΈλΆ μ 보λ₯Ό κ°μ Έμ΅λλ€.
Users user = userMapper.login(username);
if (user == null) {
log.info("μ¬μ©μ μμ...");
throw new UsernameNotFoundException("μ¬μ©μλ₯Ό μ°Ύμ μ μμ΅λλ€: " + username);
}
log.info("user :::::");
log.info(user.toString());
// π’π‘π΄ CustomUser (β‘User) μ¬μ©
CustomUser customUser = new CustomUser(user);
log.info("customuser :::::");
log.info(customUser.toString());
return customUser;
}
}
Java
볡μ¬
ν ν° Provider
β’
JwtTokenProvider.java
β¦
ν ν° μμ±
β¦
ν ν° ν΄μ
β¦
ν ν° μ ν¨μ± κ²μ¬
JwtTokenProvider.java
/**
* π JWT ν ν° κ΄λ ¨ κΈ°λ₯μ μ 곡ν΄μ£Όλ ν΄λμ€
* β
ν ν° μμ±
* β
ν ν° ν΄μ
* β
ν ν° μ ν¨μ± κ²μ¬
*/
@Slf4j
@Component
public class JwtTokenProvider {
@Autowired
private JwtProps jwtProps;
@Autowired
private UserMapper userMapper;
/*
* π©βπΌβ‘π ν ν° μμ±
*/
public String createToken(int userNo, String userId, List<String> roles) {
byte[] signingKey = getSigningKey();
// JWT ν ν° μμ±
String jwt = Jwts.builder()
.signWith(Keys.hmacShaKeyFor(signingKey), Jwts.SIG.HS512) // μλͺ
μ μ¬μ©ν ν€μ μκ³ λ¦¬μ¦ μ€μ
// .setHeaderParam("typ", SecurityConstants.TOKEN_TYPE) // deprecated (version: before 1.0)
.header() // update (version : after 1.0)
.add("typ", SecurityConstants.TOKEN_TYPE) // ν€λ μ€μ
.and()
.expiration(new Date(System.currentTimeMillis() + 864000000)) // ν ν° λ§λ£ μκ° μ€μ (10μΌ)
.claim("uno", "" + userNo) // ν΄λ μ μ€μ : μ¬μ©μ λ²νΈ
.claim("uid", userId) // ν΄λ μ μ€μ : μ¬μ©μ μμ΄λ
.claim("rol", roles) // ν΄λ μ μ€μ : κΆν
.compact();
log.info("jwt : " + jwt);
return jwt;
}
/**
* πβ‘π©βπΌ ν ν° ν΄μ
*
* Authorization : Bearer + {jwt} (authHeader)
* β‘ jwt μΆμΆ
* β‘ UsernamePasswordAuthenticationToken
* @param authHeader
* @return
* @throws Exception
*/
public UsernamePasswordAuthenticationToken getAuthentication(String authHeader) {
if(authHeader == null || authHeader.length() == 0 )
return null;
try {
// jwt μΆμΆ
String jwt = authHeader.replace("Bearer ", "");
// πβ‘π©βπΌ JWT νμ±
Jws<Claims> parsedToken = Jwts.parser()
.verifyWith(getShaKey())
.build()
.parseSignedClaims(jwt);
log.info("parsedToken : " + parsedToken);
// μΈμ¦λ μ¬μ©μ λ²νΈ
String userNo = parsedToken.getPayload().get("uno").toString();
int no = ( userNo == null ? 0 : Integer.parseInt(userNo) );
log.info("userNo : " + userNo);
// μΈμ¦λ μ¬μ©μ μμ΄λ
String userId = parsedToken.getPayload().get("uid").toString();
log.info("userId : " + userId);
// μΈμ¦λ μ¬μ©μ κΆν
Claims claims = parsedToken.getPayload();
Object roles = claims.get("rol");
log.info("roles : " + roles);
// ν ν°μ userId μλμ§ νμΈ
if( userId == null || userId.length() == 0 )
return null;
Users user = new Users();
user.setNo(no);
user.setUserId(userId);
// OK: κΆνλ λ°λ‘ Users κ°μ²΄μ λ΄μ보기
List<UserAuth> authList = ((List<?>) roles )
.stream()
.map(auth -> new UserAuth(userId, auth.toString()) )
.collect( Collectors.toList() );
user.setAuthList(authList);
// OK
// CustomeUser μ κΆν λ΄κΈ°
List<SimpleGrantedAuthority> authorities = ((List<?>) roles )
.stream()
.map(auth -> new SimpleGrantedAuthority( (String) auth ))
.collect( Collectors.toList() );
// ν ν° μ ν¨νλ©΄
// name, email λ λ΄μμ£ΌκΈ°
try {
Users userInfo = userMapper.select(no);
if( userInfo != null ) {
user.setName(userInfo.getName());
user.setEmail(userInfo.getEmail());
}
} catch (Exception e) {
log.error(e.getMessage());
log.error("ν ν° μ ν¨ -> DB μΆκ° μ 보 μ‘°νμ μλ¬ λ°μ...");
}
UserDetails userDetails = new CustomUser(user);
// OK
// new UsernamePasswordAuthenticationToken( μ¬μ©μμ 보κ°μ²΄, λΉλ°λ²νΈ, μ¬μ©μμ κΆν(λͺ©λ‘) );
return new UsernamePasswordAuthenticationToken(userDetails, null, authorities);
} catch (ExpiredJwtException exception) {
log.warn("Request to parse expired JWT : {} failed : {}", authHeader, exception.getMessage());
} catch (UnsupportedJwtException exception) {
log.warn("Request to parse unsupported JWT : {} failed : {}", authHeader, exception.getMessage());
} catch (MalformedJwtException exception) {
log.warn("Request to parse invalid JWT : {} failed : {}", authHeader, exception.getMessage());
} catch (IllegalArgumentException exception) {
log.warn("Request to parse empty or null JWT : {} failed : {}", authHeader, exception.getMessage());
}
return null;
}
//
/**
* πβ ν ν° μ ν¨μ± κ²μ¬
* @param jwt
* @return
* β true : μ ν¨
* β false : λ§λ£
*/
public boolean validateToken(String jwt) {
try {
// πβ‘π©βπΌ JWT νμ±
Jws<Claims> claims = Jwts.parser()
.verifyWith(getShaKey())
.build()
.parseSignedClaims(jwt);
log.info("::::: ν ν° λ§λ£κΈ°κ° :::::");
log.info("-> " + claims.getPayload().getExpiration());
/*
PAYLOAD
{
"exp": 1703140095, β¬
λ§λ£κΈ°ν μΆμΆ
"uid": "joeun",
"rol": [
"ROLE_USER"
]
}
*/
return !claims.getPayload().getExpiration().before(new Date());
} catch (ExpiredJwtException exception) {
log.error("Token Expired"); // ν ν° λ§λ£
return false;
} catch (JwtException exception) {
log.error("Token Tampered"); // ν ν° μμ
return false;
} catch (NullPointerException exception) {
log.error("Token is null"); // ν ν° μμ
return false;
} catch (Exception e) {
return false;
}
}
// secretKey β‘ signingKey
private byte[] getSigningKey() {
return jwtProps.getSecretKey().getBytes();
}
// secretKey β‘ (HMAC-SHA algorithms) β‘ signingKey
private SecretKey getShaKey() {
return Keys.hmacShaKeyFor(getSigningKey());
}
}
Java
볡μ¬
νν° μ€μ
β’
JWT ν ν° μΈμ¦ νν°
β¦
JwtAuthenticationFilter.java
β’
JWT ν ν° μμ² νν°
β¦
JwtRequestFilter.java
JwtAuthenticationFilter.java
@Slf4j
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
private final JwtTokenProvider jwtTokenProvider;
// μμ±μ
public JwtAuthenticationFilter( AuthenticationManager authenticationManager, JwtTokenProvider jwtTokenProvider ) {
this.authenticationManager = authenticationManager;
this.jwtTokenProvider = jwtTokenProvider;
// π νν° URL κ²½λ‘ μ€μ : /login
setFilterProcessesUrl(SecurityConstants.AUTH_LOGIN_URL);
}
/**
* π μΈμ¦ μλ λ©μλ
* : /login κ²½λ‘λ‘ (username, password) λ₯Ό μμ²νλ©΄ μ΄ νν°μμ κ±Έλ € μΈμ¦μ μλν©λλ€.
* β
Authentication μΈμ¦ μλν μ¬μ©μ μΈμ¦ κ°μ²΄λ₯Ό λ°ννμ¬, μν리ν°κ° μΈμ¦ μ±κ³΅ μ¬λΆλ₯Ό νλ¨νκ² ν©λλ€.
* @param request
* @param response
* @return
* @throws AuthenticationException
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
String username = request.getParameter("username");
String password = request.getParameter("password");
log.info("username : " + username);
log.info("password : " + password);
// μ¬μ©μ μΈμ¦μ 보 κ°μ²΄ μμ±
Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);
// μ¬μ©μ μΈμ¦ (λ‘κ·ΈμΈ)
authentication = authenticationManager.authenticate(authentication);
/*
π authenticate() μΈμ¦ μ²λ¦¬ νλ‘μΈμ€
1οΈβ£ μ£Όμ΄μ§ Authentication κ°μ²΄μμ μ¬μ©μμ μμ΄λλ₯Ό μΆμΆν©λλ€.
2οΈβ£ UserDetailsServiceλ₯Ό μ¬μ©νμ¬ ν΄λΉ μμ΄λμ λν UserDetails κ°μ²΄λ₯Ό κ°μ Έμ΅λλ€.
3οΈβ£ κ°μ Έμ¨ UserDetails κ°μ²΄μμ μ μ₯λ λΉλ°λ²νΈλ₯Ό νμΈνκΈ° μν΄ PasswordEncoderλ₯Ό μ¬μ©ν©λλ€.
4οΈβ£ μ¬μ©μκ° μ 곡ν λΉλ°λ²νΈμ μ μ₯λ λΉλ°λ²νΈκ° μΌμΉνλμ§ νμΈν©λλ€.
5οΈβ£ μΈμ¦μ΄ μ±κ³΅νλ©΄, μλ‘μ΄ Authentication κ°μ²΄λ₯Ό μμ±νμ¬ λ°νν©λλ€.
β
μΈμ¦ μ¬λΆλ₯Ό, isAuthenticated() β‘ true λ‘ νμΈν μ μμ΅λλ€.
*/
log.info("authenticationManager : " + authenticationManager);
log.info("authentication : " + authentication);
log.info("μΈμ¦ μ¬λΆ(isAuthenticated) : " + authentication.isAuthenticated());
// μΈμ¦ μ€ν¨ (username, password λΆμΌμΉ)
if( !authentication.isAuthenticated() ) {
log.info("μΈμ¦ μ€ν¨ : μμ΄λμ λΉλ°λ²νΈκ° μΌμΉνμ§ μμ΅λλ€.");
response.setStatus(401);
}
return authentication;
}
/**
* β μΈμ¦ μ±κ³΅ λ©μλ
* : attemptAuthentication() νΈμΆ ν, λ°νλ Authentication - μ¬μ©μ μΈμ¦ κ°μ²΄κ° μΈμ¦λ κ²μ΄ νμΈλλ©΄, νΈμΆλ©λλ€.
*
* β‘ π JWT
* : λ‘κ·ΈμΈ μΈμ¦μ μ±κ³΅νμΌλ―λ‘, JWT ν ν°μ μμ±νμ¬
* μλ΅(response) ν€λμ jwt ν ν°μ λ΄μ μλ΅ν©λλ€.
* π { Authorization : Bearer + {jwt} }
* @param request
* @param response
* @param chain
* @param authentication
* @throws IOException
* @throws ServletException
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authentication) throws IOException, ServletException {
log.info("μΈμ¦ μ±κ³΅ (auth SUCCESS) : ");
CustomUser user = ((CustomUser) authentication.getPrincipal());
int userNo = user.getUser().getNo();
String userId = user.getUser().getUserId();
List<String> roles = user.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList());
// π JWT
String token = jwtTokenProvider.createToken(userNo, userId, roles);
// π { Authorization : Bearer + {jwt} }
response.addHeader(SecurityConstants.TOKEN_HEADER, SecurityConstants.TOKEN_PREFIX + token);
response.setStatus(200);
}
}
Java
볡μ¬
JwtRequestFilter.java
@Slf4j
public class JwtRequestFilter extends OncePerRequestFilter {
private final AuthenticationManager authenticationManager;
private final JwtTokenProvider jwtTokenProvider;
// μμ±μ
public JwtRequestFilter( AuthenticationManager authenticationManager, JwtTokenProvider jwtTokenProvider ) {
this.authenticationManager = authenticationManager;
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// HTTP ν€λμμ ν ν°μ κ°μ Έμ΄
String header = request.getHeader(SecurityConstants.TOKEN_HEADER);
log.info("authorization : " + header);
//β
Bearer + {jwt} 체ν¬
// ν€λκ° μκ±°λ νμμ΄ μ¬λ°λ₯΄μ§ μμΌλ©΄ λ€μ νν°λ‘ μ§ν
if (header == null || header.length() == 0 || !header.startsWith(SecurityConstants.TOKEN_PREFIX)) {
filterChain.doFilter(request, response);
return;
}
// π JWT
// Bearer + ${jwt} β‘ "Bearer " μ κ±°
String jwt = header.replace(SecurityConstants.TOKEN_PREFIX, "");
// ν ν°μ μ¬μ©νμ¬ Authentication κ°μ²΄ μμ±
Authentication authentication = jwtTokenProvider.getAuthentication(jwt);
// ν ν° μ ν¨ κ²μ¬ (ν ν°μ΄ λ§λ£λμ§ μμμΌλ©΄)
if( jwtTokenProvider.validateToken(jwt) ) {
log.info("μ ν¨ν JWT ν ν°μ
λλ€.");
// π©βπΌ [λ‘κ·ΈμΈ]
// SecurityContextHolder(μ¬μ©μ 보μμ 보λ₯Ό λ΄λ κ°μ²΄)μ
// Authentication(μ¬μ©μ μΈμ¦ μ 보) κ°μ²΄λ₯Ό μ€μ
SecurityContextHolder.getContext().setAuthentication(authentication);
}
// λ€μ νν°λ‘ μ§ν
filterChain.doFilter(request, response);
}
}
Java
볡μ¬