pamapi/src/doc/sql/20230803_j.sql | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/doc/sql/executed/20230727_j.sql | 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/doc/登出API/登出API.txt | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/security/jwt/JWTFilter.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/web/rest/UserJWTController.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 |
pamapi/src/doc/sql/20230803_j.sql
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,7 @@ -- çºäºå¼±é»ææå¨jwt tokenç»åºå¾é åå ¥é»åå®è®token失æ CREATE TABLE public.tokens_black_list ( jwt_token text NOT NULL, created_date timestamp NULL, CONSTRAINT tokens_black_list_pkey PRIMARY KEY (jwt_token) ); pamapi/src/doc/sql/executed/20230727_j.sql
pamapi/src/doc/µn¥XAPI/µn¥XAPI.txt
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,3 @@ http post : http://localhost:8080/api/logout pamapi/src/main/java/com/pollex/pam/config/SecurityConfiguration.java
@@ -80,6 +80,7 @@ .authorizeRequests() .antMatchers("/api/access_analysis/**").permitAll() .antMatchers("/api/authenticate").permitAll() .antMatchers("/api/logout").permitAll() .antMatchers("/api/register").permitAll() .antMatchers("/api/activate").permitAll() .antMatchers("/api/testLogin/**").permitAll() pamapi/src/main/java/com/pollex/pam/security/jwt/JWTFilter.java
@@ -1,15 +1,24 @@ package com.pollex.pam.security.jwt; import java.io.IOException; import java.util.Optional; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.GenericFilterBean; import com.pollex.pam.business.domain.TokenBlackList; import com.pollex.pam.business.repository.TokenBlackListRepository; /** * Filters incoming requests and installs a Spring Security principal if a header corresponding to a valid user is @@ -22,6 +31,7 @@ public static final String AUTHORIZATION_TOKEN = "access_token"; private final TokenProvider tokenProvider; public JWTFilter(TokenProvider tokenProvider) { this.tokenProvider = tokenProvider; @@ -32,19 +42,31 @@ throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; String jwt = resolveToken(httpServletRequest); if(StringUtils.hasText(jwt) && !jwt.equals("null")) { boolean isBlackToken = this.tokenProvider.isBlackListToken(jwt); if(isBlackToken) { HttpServletResponse response = (HttpServletResponse) servletResponse; response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } } if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) { Authentication authentication = this.tokenProvider.getAuthentication(jwt); Authentication authentication = this.tokenProvider.getAuthentication(jwt); SecurityContextHolder.getContext().setAuthentication(authentication); } filterChain.doFilter(servletRequest, servletResponse); } private String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader(AUTHORIZATION_HEADER); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } String jwt = request.getParameter(AUTHORIZATION_TOKEN); if (StringUtils.hasText(jwt)) { return jwt; } pamapi/src/main/java/com/pollex/pam/security/jwt/TokenProvider.java
@@ -7,8 +7,12 @@ import java.security.Key; import java.util.*; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -16,6 +20,10 @@ import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import com.pollex.pam.business.domain.TokenBlackList; import com.pollex.pam.business.repository.TokenBlackListRepository; import tech.jhipster.config.JHipsterProperties; @Component @@ -33,6 +41,9 @@ private final long tokenValidityInMilliseconds; private final long tokenValidityInMillisecondsForRememberMe; @Autowired TokenBlackListRepository tokenBlackListRepository; public TokenProvider(JHipsterProperties jHipsterProperties) { byte[] keyBytes; @@ -102,4 +113,9 @@ } return false; } public boolean isBlackListToken(String jwt) { Optional<TokenBlackList> tokenBlack = tokenBlackListRepository.findById(jwt); return tokenBlack.isPresent(); } } pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java
@@ -58,7 +58,8 @@ return getConsultantTokenAndRecordLoginTime(account, credentials); } else { throw new EServiceErrorException(eServiceResponse.getMsg()); log.debug("account:{},error:{}",account,eServiceResponse.getMsg()); throw new EServiceErrorException("帳èå¯ç¢¼é¯èª¤"); } } @@ -69,7 +70,7 @@ } private UsernamePasswordAuthenticationToken getConsultantTokenAndRecordLoginTime(String account, String credential) throws ConsultantDisableException { Consultant consultant = consultantRepository.findOneByAgentNo(account).orElseThrow(() -> new UsernameNotFoundException("該顧åè³æä¸¦ä¸å卿¼åªåå¹³å°ç³»çµ±ä¸")); Consultant consultant = consultantRepository.findOneByAgentNo(account).orElseThrow(() -> new UsernameNotFoundException("帳èå¯ç¢¼é¯èª¤")); List<GrantedAuthority> grantedAuths = Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(account, credential, grantedAuths); pamapi/src/main/java/com/pollex/pam/web/rest/UserJWTController.java
@@ -3,8 +3,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.pollex.pam.security.jwt.JWTFilter; import com.pollex.pam.security.jwt.TokenProvider; import com.pollex.pam.business.domain.TokenBlackList; import com.pollex.pam.business.repository.TokenBlackListRepository; import com.pollex.pam.business.web.vm.LoginVM; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -12,6 +19,7 @@ import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; /** @@ -24,6 +32,9 @@ private final TokenProvider tokenProvider; private final AuthenticationManagerBuilder authenticationManagerBuilder; @Autowired TokenBlackListRepository tokenBlackListRepository; public UserJWTController(TokenProvider tokenProvider, AuthenticationManagerBuilder authenticationManagerBuilder) { this.tokenProvider = tokenProvider; @@ -44,6 +55,25 @@ httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt); return new ResponseEntity<>(new JWTToken(jwt), httpHeaders, HttpStatus.OK); } @PostMapping("/logout") public void logout(HttpServletRequest servletRequest) { String jwtToken = resolveToken(servletRequest); TokenBlackList blackList = new TokenBlackList(jwtToken); tokenBlackListRepository.save(blackList); } private String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader(JWTFilter.AUTHORIZATION_HEADER); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } String jwt = request.getParameter(JWTFilter.AUTHORIZATION_TOKEN); if (StringUtils.hasText(jwt)) { return jwt; } return null; } /** * Object to return as body in JWT Authentication.