Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
358 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
FROM openjdk:8u201-jdk-alpine3.9 | ||
|
||
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 | ||
|
||
VOLUME /tmp | ||
|
||
ADD target/_01SpringSecurityDemo01-0.0.1-SNAPSHOT.jar app.jar | ||
|
||
ENTRYPOINT ["java","-jar","app.jar"] | ||
|
||
EXPOSE 8081 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
src/main/java/com/al/_01springsecuritydemo01/common/RestResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package com.al._01springsecuritydemo01.common; | ||
|
||
import java.util.HashMap; | ||
|
||
/** | ||
* API 接口返回结果封装 | ||
*/ | ||
public class RestResult extends HashMap<String, Object> { | ||
private static final long serialVersionUID = 1L; | ||
// 状态码 | ||
public static final String CODE_TAG = "code"; | ||
// 返回内容 | ||
public static final String MSG_TAG = "msg"; | ||
// 数据对象 | ||
public static final String DATA_TAG = "data"; | ||
|
||
public RestResult() { | ||
|
||
} | ||
|
||
public RestResult(int code, String msg) { | ||
super.put(CODE_TAG, code); | ||
super.put(MSG_TAG, msg); | ||
} | ||
|
||
public RestResult(int code, String msg, Object data) { | ||
super.put(CODE_TAG, code); | ||
super.put(MSG_TAG, msg); | ||
if (data != null) { | ||
super.put(DATA_TAG, data); | ||
} | ||
} | ||
|
||
public static RestResult success() { | ||
return new RestResult(200, "成功"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/main/java/com/al/_01springsecuritydemo01/config/jwt/JwtAuthService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.al._01springsecuritydemo01.config.jwt; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.security.authentication.AuthenticationManager; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.stereotype.Service; | ||
|
||
import com.al._01springsecuritydemo01.entity.User; | ||
|
||
@Service | ||
public class JwtAuthService { | ||
@Autowired | ||
private JwtTokenUtils jwtTokenUtils; | ||
|
||
@Autowired | ||
private AuthenticationManager authenticationManager; | ||
|
||
public String login(String username, String password) { | ||
Authentication authentication = null; | ||
try { | ||
authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); | ||
} catch (Exception e) { | ||
throw new RuntimeException("用户名或密码有误"); | ||
} | ||
User loginUser = (User) authentication.getPrincipal(); | ||
return jwtTokenUtils.generateToken(loginUser); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/com/al/_01springsecuritydemo01/config/jwt/JwtAuthTokenFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.al._01springsecuritydemo01.config.jwt; | ||
|
||
import java.io.IOException; | ||
|
||
import javax.servlet.FilterChain; | ||
import javax.servlet.ServletException; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
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.core.userdetails.UserDetailsService; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.ObjectUtils; | ||
import org.springframework.web.filter.OncePerRequestFilter; | ||
|
||
@Component | ||
public class JwtAuthTokenFilter extends OncePerRequestFilter { | ||
@Autowired | ||
private UserDetailsService userDetailsService; | ||
|
||
@Autowired | ||
private JwtTokenUtils jwtTokenUtils; | ||
|
||
@Override | ||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { | ||
String jwtToken = request.getHeader(jwtTokenUtils.getHeader()); | ||
|
||
if (!ObjectUtils.isEmpty(jwtToken)) { | ||
String username = jwtTokenUtils.getUsernameFromToken(jwtToken); | ||
|
||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { | ||
UserDetails userDetails = userDetailsService.loadUserByUsername(username); | ||
if (jwtTokenUtils.validateToken(jwtToken, userDetails)) { | ||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); | ||
// 交给SpringSecurity管理,在之后的过滤器不会被拦截进行二次授权了 | ||
SecurityContextHolder.getContext().setAuthentication(authenticationToken); | ||
} | ||
} | ||
} | ||
chain.doFilter(request, response); | ||
} | ||
} |
168 changes: 168 additions & 0 deletions
168
src/main/java/com/al/_01springsecuritydemo01/config/jwt/JwtTokenUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package com.al._01springsecuritydemo01.config.jwt; | ||
|
||
|
||
import java.security.Key; | ||
import java.util.Date; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import javax.crypto.spec.SecretKeySpec; | ||
import javax.xml.bind.DatatypeConverter; | ||
|
||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.stereotype.Component; | ||
|
||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.SignatureAlgorithm; | ||
import lombok.Data; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Data | ||
@Component | ||
@Slf4j | ||
public class JwtTokenUtils { | ||
|
||
@Value("${token.secret}") | ||
private String secret; | ||
|
||
@Value("${token.expireTime}") | ||
private Long expiration; | ||
|
||
@Value("${token.header}") | ||
private String header; | ||
|
||
|
||
private static Key KEY = null; | ||
|
||
/** | ||
* 生成token令牌 | ||
* | ||
* @param userDetails 用户 | ||
* @return 令token牌 | ||
*/ | ||
public String generateToken(UserDetails userDetails) { | ||
log.info("[JwtTokenUtils] generateToken " + userDetails.toString()); | ||
Map<String, Object> claims = new HashMap<>(2); | ||
claims.put("sub", userDetails.getUsername()); | ||
claims.put("created", new Date()); | ||
|
||
return generateToken(claims); | ||
} | ||
|
||
|
||
/** | ||
* 从令牌中获取用户名 | ||
* | ||
* @param token 令牌 | ||
* @return 用户名 | ||
*/ | ||
public String getUsernameFromToken(String token) { | ||
String username = null; | ||
try { | ||
Claims claims = getClaimsFromToken(token); | ||
username = claims.get("sub", String.class); | ||
log.info("从令牌中获取用户名:" + username); | ||
} catch (Exception e) { | ||
username = null; | ||
} | ||
return username; | ||
} | ||
|
||
/** | ||
* 判断令牌是否过期 | ||
* | ||
* @param token 令牌 | ||
* @return 是否过期 | ||
*/ | ||
public Boolean isTokenExpired(String token) { | ||
try { | ||
Claims claims = getClaimsFromToken(token); | ||
Date expiration = claims.getExpiration(); | ||
return expiration.before(new Date()); | ||
} catch (Exception e) { | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* 刷新令牌 | ||
* | ||
* @param token 原令牌 | ||
* @return 新令牌 | ||
*/ | ||
public String refreshToken(String token) { | ||
String refreshedToken; | ||
try { | ||
Claims claims = getClaimsFromToken(token); | ||
claims.put("created", new Date()); | ||
|
||
|
||
refreshedToken = generateToken(claims); | ||
} catch (Exception e) { | ||
refreshedToken = null; | ||
} | ||
return refreshedToken; | ||
} | ||
|
||
/** | ||
* 验证令牌 | ||
* | ||
* @param token 令牌 | ||
* @param userDetails 用户 | ||
* @return 是否有效 | ||
*/ | ||
public Boolean validateToken(String token, UserDetails userDetails) { | ||
|
||
String username = getUsernameFromToken(token); | ||
return (username.equals(userDetails.getUsername()) && | ||
!isTokenExpired(token)); | ||
} | ||
|
||
|
||
/** | ||
* 从claims生成令牌,如果看不懂就看谁调用它 | ||
* | ||
* @param claims 数据声明 | ||
* @return 令牌 | ||
*/ | ||
private String generateToken(Map<String, Object> claims) { | ||
Date expirationDate = new Date(System.currentTimeMillis() + expiration); | ||
return Jwts.builder().setClaims(claims) | ||
.setExpiration(expirationDate) | ||
.signWith(SignatureAlgorithm.HS256, getKeyInstance()) | ||
.compact(); | ||
} | ||
|
||
/** | ||
* 从令牌中获取数据声明,如果看不懂就看谁调用它 | ||
* | ||
* @param token 令牌 | ||
* @return 数据声明 | ||
*/ | ||
private Claims getClaimsFromToken(String token) { | ||
Claims claims = null; | ||
|
||
try { | ||
claims = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(token).getBody(); | ||
// claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); | ||
} catch (Exception e) { | ||
claims = null; | ||
} | ||
return claims; | ||
} | ||
|
||
|
||
private Key getKeyInstance() { | ||
if (KEY == null) { | ||
synchronized (JwtTokenUtils.class) { | ||
if (KEY == null) {// 双重锁 | ||
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secret); | ||
KEY = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName()); | ||
} | ||
} | ||
} | ||
return KEY; | ||
} | ||
} |
Oops, something went wrong.