Commit 95688e400b6974953505c159f8fbf9d65784c724

Authored by 648540858
1 parent ec90519c

初步实现登录返回token

@@ -216,8 +216,6 @@ @@ -216,8 +216,6 @@
216 <version>4.10.0</version> 216 <version>4.10.0</version>
217 </dependency> 217 </dependency>
218 218
219 -  
220 -  
221 <!-- okhttp-digest --> 219 <!-- okhttp-digest -->
222 <dependency> 220 <dependency>
223 <groupId>io.github.rburgst</groupId> 221 <groupId>io.github.rburgst</groupId>
@@ -226,10 +224,17 @@ @@ -226,10 +224,17 @@
226 </dependency> 224 </dependency>
227 225
228 <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> 226 <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
  227 +<!-- <dependency>-->
  228 +<!-- <groupId>net.sf.kxml</groupId>-->
  229 +<!-- <artifactId>kxml2</artifactId>-->
  230 +<!-- <version>2.3.0</version>-->
  231 +<!-- </dependency>-->
  232 +
  233 + <!-- jwt实现 -->
229 <dependency> 234 <dependency>
230 - <groupId>net.sf.kxml</groupId>  
231 - <artifactId>kxml2</artifactId>  
232 - <version>2.3.0</version> 235 + <groupId>org.bitbucket.b_c</groupId>
  236 + <artifactId>jose4j</artifactId>
  237 + <version>0.9.3</version>
233 </dependency> 238 </dependency>
234 239
235 <!--反向代理--> 240 <!--反向代理-->
src/main/java/com/genersoft/iot/vmp/conf/security/AnonymousAuthenticationEntryPoint.java
1 package com.genersoft.iot.vmp.conf.security; 1 package com.genersoft.iot.vmp.conf.security;
2 2
3 import com.alibaba.fastjson2.JSONObject; 3 import com.alibaba.fastjson2.JSONObject;
  4 +import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
4 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 5 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
5 -import org.slf4j.Logger;  
6 -import org.slf4j.LoggerFactory; 6 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
7 import org.springframework.security.core.AuthenticationException; 7 import org.springframework.security.core.AuthenticationException;
  8 +import org.springframework.security.core.context.SecurityContextHolder;
8 import org.springframework.security.web.AuthenticationEntryPoint; 9 import org.springframework.security.web.AuthenticationEntryPoint;
9 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
10 11
@@ -17,12 +18,17 @@ import java.io.IOException; @@ -17,12 +18,17 @@ import java.io.IOException;
17 * @author lin 18 * @author lin
18 */ 19 */
19 @Component 20 @Component
20 -public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint {  
21 -  
22 - private final static Logger logger = LoggerFactory.getLogger(DefaultUserDetailsServiceImpl.class); 21 +public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint {
23 22
24 @Override 23 @Override
25 public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { 24 public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {
  25 + System.err.println(e.getMessage());
  26 + String jwt = request.getHeader(JwtUtils.getHeader());
  27 + JwtUser jwtUser = JwtUtils.verifyToken(jwt);
  28 + String username = jwtUser.getUserName();
  29 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() );
  30 + SecurityContextHolder.getContext().setAuthentication(token);
  31 + System.out.println(jwt);
26 // 允许跨域 32 // 允许跨域
27 String origin = request.getHeader("Origin"); 33 String origin = request.getHeader("Origin");
28 response.setHeader("Access-Control-Allow-Credentials", "true"); 34 response.setHeader("Access-Control-Allow-Credentials", "true");
src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
1 package com.genersoft.iot.vmp.conf.security; 1 package com.genersoft.iot.vmp.conf.security;
2 2
3 -import java.time.LocalDateTime;  
4 - 3 +import com.alibaba.excel.util.StringUtils;
  4 +import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
  5 +import com.genersoft.iot.vmp.service.IUserService;
  6 +import com.genersoft.iot.vmp.storager.dao.dto.User;
5 import org.slf4j.Logger; 7 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
7 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
@@ -10,10 +12,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; @@ -10,10 +12,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
10 import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 import org.springframework.security.core.userdetails.UsernameNotFoundException;
11 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
12 14
13 -import com.alibaba.excel.util.StringUtils;  
14 -import com.genersoft.iot.vmp.conf.security.dto.LoginUser;  
15 -import com.genersoft.iot.vmp.service.IUserService;  
16 -import com.genersoft.iot.vmp.storager.dao.dto.User; 15 +import java.time.LocalDateTime;
17 16
18 /** 17 /**
19 * 用户登录认证逻辑 18 * 用户登录认证逻辑
@@ -45,4 +44,8 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService { @@ -45,4 +44,8 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService {
45 } 44 }
46 45
47 46
  47 +
  48 +
  49 +
  50 +
48 } 51 }
src/main/java/com/genersoft/iot/vmp/conf/security/InvalidSessionHandler.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.conf.security;  
2 -  
3 -import org.slf4j.Logger;  
4 -import org.slf4j.LoggerFactory;  
5 -import org.springframework.security.web.session.InvalidSessionStrategy;  
6 -  
7 -import javax.servlet.ServletException;  
8 -import javax.servlet.http.HttpServletRequest;  
9 -import javax.servlet.http.HttpServletResponse;  
10 -import java.io.IOException;  
11 -  
12 -/**  
13 - * 登录超时的处理  
14 - */  
15 -public class InvalidSessionHandler implements InvalidSessionStrategy {  
16 -  
17 - private final static Logger logger = LoggerFactory.getLogger(InvalidSessionHandler.class);  
18 -  
19 - @Override  
20 - public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse httpServletResponse) throws IOException, ServletException {  
21 - String username = request.getParameter("username");  
22 - logger.info("[登录超时] - [{}]", username);  
23 - }  
24 -}  
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.security;
  2 +
  3 +import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
  4 +import org.apache.commons.lang3.StringUtils;
  5 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  6 +import org.springframework.security.core.context.SecurityContextHolder;
  7 +import org.springframework.stereotype.Component;
  8 +import org.springframework.web.filter.OncePerRequestFilter;
  9 +
  10 +import javax.servlet.FilterChain;
  11 +import javax.servlet.ServletException;
  12 +import javax.servlet.http.HttpServletRequest;
  13 +import javax.servlet.http.HttpServletResponse;
  14 +import java.io.IOException;
  15 +import java.util.ArrayList;
  16 +
  17 +/**
  18 + * jwt token 过滤器
  19 + */
  20 +
  21 +@Component
  22 +public class JwtAuthenticationFilter extends OncePerRequestFilter {
  23 +
  24 +
  25 + @Override
  26 + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
  27 + String jwt = request.getHeader(JwtUtils.getHeader());
  28 + // 这里如果没有jwt,继续往后走,因为后面还有鉴权管理器等去判断是否拥有身份凭证,所以是可以放行的
  29 + // 没有jwt相当于匿名访问,若有一些接口是需要权限的,则不能访问这些接口
  30 + if (StringUtils.isBlank(jwt)) {
  31 + chain.doFilter(request, response);
  32 + return;
  33 + }
  34 +
  35 +
  36 + JwtUser jwtUser = JwtUtils.verifyToken(jwt);
  37 + String username = jwtUser.getUserName();
  38 + // TODO 处理各个状态
  39 + switch (jwtUser.getStatus()){
  40 + case EXPIRED:
  41 + response.setStatus(400);
  42 + chain.doFilter(request, response);
  43 + // 异常
  44 + return;
  45 + case EXCEPTION:
  46 + // 过期
  47 + response.setStatus(400);
  48 + chain.doFilter(request, response);
  49 + return;
  50 + case EXPIRING_SOON:
  51 + // 即将过期
  52 +// return;
  53 + default:
  54 + }
  55 +
  56 +// String password = SecurityUtils.encryptPassword(jwtUser.getPassword());
  57 +// user.setPassword(password);
  58 +
  59 + // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
  60 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword(), new ArrayList<>() );
  61 + SecurityContextHolder.getContext().setAuthentication(token);
  62 + chain.doFilter(request, response);
  63 + }
  64 +
  65 +}
src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.security;
  2 +
  3 +import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
  4 +import org.jose4j.json.JsonUtil;
  5 +import org.jose4j.jwk.RsaJsonWebKey;
  6 +import org.jose4j.jws.AlgorithmIdentifiers;
  7 +import org.jose4j.jws.JsonWebSignature;
  8 +import org.jose4j.jwt.JwtClaims;
  9 +import org.jose4j.jwt.NumericDate;
  10 +import org.jose4j.jwt.consumer.ErrorCodes;
  11 +import org.jose4j.jwt.consumer.InvalidJwtException;
  12 +import org.jose4j.jwt.consumer.JwtConsumer;
  13 +import org.jose4j.jwt.consumer.JwtConsumerBuilder;
  14 +import org.jose4j.lang.JoseException;
  15 +import org.slf4j.Logger;
  16 +import org.slf4j.LoggerFactory;
  17 +
  18 +import java.security.PrivateKey;
  19 +import java.time.LocalDateTime;
  20 +import java.time.ZoneOffset;
  21 +
  22 +public class JwtUtils {
  23 +
  24 + private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
  25 +
  26 + private static final String HEADER = "Access-Token";
  27 + private static final String AUDIENCE = "Audience";
  28 +
  29 + private static final long EXPIRED_THRESHOLD = 10 * 60;
  30 +
  31 + private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae";
  32 + private static final String privateKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\",\"d\":\"ed7U_k3rJ4yTk70JtRSIfjKGiEb67BO1TabcymnljKO7RU8nage84zZYuSu_XpQsHk6P1f0Gzxkicghm_Er-FrfVn2pp70Xu52z3yRd6BJUgWLDFk97ngScIyw5OiULKU9SrZk2frDpftNCSUcIgb50F8m0QAnBa_CdPsQKbuuhLv8V8tBAV7F_lAwvSBgu56wRo3hPz5dWH8YeXM7XBfQ9viFMNEKd21sP_j5C7ueUnXT66nBxe3ZJEU3iuMYM6D6dB_KW2GfZC6WmTgvGhhxJD0h7aYmfjkD99MDleB7SkpbvoODOqiQ5Epb7Nyh6kv5u4KUv2CJYtATLZkUeMkQ\",\"p\":\"uBUjWPWtlGksmOqsqCNWksfqJvMcnP_8TDYN7e4-WnHL4N-9HjRuPDnp6kHvCIEi9SEfxm7gNxlRcWegvNQr3IZCz7TnCTexXc5NOklB9OavWFla6u-s3Thn6Tz45-EUjpJr0VJMxhO-KxGmuTwUXBBp4vN6K2qV6rQNFmgkWzk\",\"q\":\"tW_i7cCec56bHkhITL_79dXHz_PLC_f7xlynmlZJGU_d6mqOKmLBNBbTMLnYW8uAFiFzWxDeDHh1o5uF0mSQR-Z1Fg35OftnpbWpy0Cbc2la5WgXQjOwtG1eLYIY2BD3-wQ1VYDBCvowr4FDi-sngxwLqvwmrJ0xjhi99O-Gzcs\",\"dp\":\"q1d5jE85Hz_6M-eTh_lEluEf0NtPEc-vvhw-QO4V-cecNpbrCBdTWBmr4dE3NdpFeJc5ZVFEv-SACyei1MBEh0ItI_pFZi4BmMfy2ELh8ptaMMkTOESYyVy8U7veDq9RnBcr5i1Nqr0rsBkA77-9T6gzdvycBZdzLYAkAmwzEvk\",\"dq\":\"q29A2K08Crs-jmp2Bi8Q_8QzvIX6wSBbwZ4ir24AO-5_HNP56IrPS0yV2GCB0pqCOGb6_Hz_koDvhtuYoqdqvMVAtMoXR3YJBUaVXPt65p4RyNmFwIPe31zHs_BNUTsXVRMw4c16mci03-Af1sEm4HdLfxAp6sfM3xr5wcnhcek\",\"qi\":\"rHPgVTyHUHuYzcxfouyBfb1XAY8nshwn0ddo81o1BccD4Z7zo5It6SefDHjxCAbcmbiCcXBSooLcY-NF5FMv3fg19UE21VyLQltHcVjRRp2tRs4OHcM8yaXIU2x6N6Z6BP2tOksHb9MOBY1wAQzFOAKg_G4Sxev6-_6ud6RISuc\"}";
  33 + private static final String publicKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\"}";
  34 +
  35 + /**
  36 + * token过期时间(分钟)
  37 + */
  38 + public static final long expirationTime = 30;
  39 +
  40 + public static String createToken(String username, String password) {
  41 + try {
  42 + /**
  43 + * “iss” (issuer) 发行人
  44 + *
  45 + * “sub” (subject) 主题
  46 + *
  47 + * “aud” (audience) 接收方 用户
  48 + *
  49 + * “exp” (expiration time) 到期时间
  50 + *
  51 + * “nbf” (not before) 在此之前不可用
  52 + *
  53 + * “iat” (issued at) jwt的签发时间
  54 + */
  55 + //Payload
  56 + JwtClaims claims = new JwtClaims();
  57 + claims.setGeneratedJwtId();
  58 + claims.setIssuedAtToNow();
  59 + // 令牌将过期的时间 分钟
  60 + claims.setExpirationTimeMinutesInTheFuture(expirationTime);
  61 + claims.setNotBeforeMinutesInThePast(0);
  62 + claims.setSubject("login");
  63 + claims.setAudience(AUDIENCE);
  64 + //添加自定义参数,必须是字符串类型
  65 + claims.setClaim("username", username);
  66 + claims.setClaim("password", password);
  67 +
  68 + //jws
  69 + JsonWebSignature jws = new JsonWebSignature();
  70 + //签名算法RS256
  71 + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
  72 + jws.setKeyIdHeaderValue(keyId);
  73 + jws.setPayload(claims.toJson());
  74 +
  75 + PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyStr)).getPrivateKey();
  76 + jws.setKey(privateKey);
  77 +
  78 + //get token
  79 + String idToken = jws.getCompactSerialization();
  80 + return idToken;
  81 + } catch (JoseException e) {
  82 + logger.error("[Token生成失败]: {}", e.getMessage());
  83 + }
  84 +
  85 + return null;
  86 + }
  87 +
  88 + public static String getHeader() {
  89 + return HEADER;
  90 + }
  91 +
  92 +
  93 + public static JwtUser verifyToken(String token) {
  94 +
  95 + JwtUser jwtUser = new JwtUser();
  96 +
  97 + try {
  98 + JwtConsumer consumer = new JwtConsumerBuilder()
  99 + .setRequireExpirationTime()
  100 + .setMaxFutureValidityInMinutes(5256000)
  101 + .setAllowedClockSkewInSeconds(30)
  102 + .setRequireSubject()
  103 + //.setExpectedIssuer("")
  104 + .setExpectedAudience(AUDIENCE)
  105 + .setVerificationKey(new RsaJsonWebKey(JsonUtil.parseJson(publicKeyStr)).getPublicKey())
  106 + .build();
  107 +
  108 + JwtClaims claims = consumer.processToClaims(token);
  109 + NumericDate expirationTime = claims.getExpirationTime();
  110 + // 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
  111 + // 剩余时间 (秒)
  112 + long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
  113 + if (timeRemaining < 5 * 60) {
  114 + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
  115 + }else {
  116 + jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
  117 + }
  118 +
  119 + String username = (String) claims.getClaimValue("username");
  120 + String password = (String) claims.getClaimValue("password");
  121 + jwtUser.setUserName(username);
  122 + jwtUser.setPassword(password);
  123 +
  124 + return jwtUser;
  125 + } catch (InvalidJwtException e) {
  126 + if (e.hasErrorCode(ErrorCodes.EXPIRED)) {
  127 + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
  128 + }else {
  129 + jwtUser.setStatus(JwtUser.TokenStatus.EXCEPTION);
  130 + }
  131 + return jwtUser;
  132 + }catch (Exception e) {
  133 + logger.error("[Token解析失败]: {}", e.getMessage());
  134 + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
  135 + return jwtUser;
  136 + }
  137 + }
  138 +}
src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java
@@ -21,7 +21,16 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler { @@ -21,7 +21,16 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler {
21 21
22 @Override 22 @Override
23 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { 23 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
24 - String username = request.getParameter("username");  
25 - logger.info("[登录成功] - [{}]", username); 24 +// String username = request.getParameter("username");
  25 +// httpServletResponse.setContentType("application/json;charset=UTF-8");
  26 +// // 生成JWT,并放置到请求头中
  27 +// String jwt = JwtUtils.createToken(authentication.getName(), );
  28 +// httpServletResponse.setHeader(JwtUtils.getHeader(), jwt);
  29 +// ServletOutputStream outputStream = httpServletResponse.getOutputStream();
  30 +// outputStream.write(JSON.toJSONString(ErrorCode.SUCCESS).getBytes(StandardCharsets.UTF_8));
  31 +// outputStream.flush();
  32 +// outputStream.close();
  33 +
  34 +// logger.info("[登录成功] - [{}]", username);
26 } 35 }
27 } 36 }
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java
1 package com.genersoft.iot.vmp.conf.security; 1 package com.genersoft.iot.vmp.conf.security;
2 2
3 import com.genersoft.iot.vmp.conf.security.dto.LoginUser; 3 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
  4 +import com.genersoft.iot.vmp.storager.dao.dto.User;
4 import org.springframework.security.authentication.AuthenticationManager; 5 import org.springframework.security.authentication.AuthenticationManager;
5 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 6 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
6 import org.springframework.security.core.Authentication; 7 import org.springframework.security.core.Authentication;
@@ -9,6 +10,7 @@ import org.springframework.security.core.context.SecurityContextHolder; @@ -9,6 +10,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
9 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 10 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
10 11
11 import javax.security.sasl.AuthenticationException; 12 import javax.security.sasl.AuthenticationException;
  13 +import java.time.LocalDateTime;
12 14
13 public class SecurityUtils { 15 public class SecurityUtils {
14 16
@@ -25,10 +27,16 @@ public class SecurityUtils { @@ -25,10 +27,16 @@ public class SecurityUtils {
25 public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException { 27 public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException {
26 //使用security框架自带的验证token生成器 也可以自定义。 28 //使用security框架自带的验证token生成器 也可以自定义。
27 UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password); 29 UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password);
28 - Authentication authenticate = authenticationManager.authenticate(token);  
29 - SecurityContextHolder.getContext().setAuthentication(authenticate);  
30 - LoginUser user = (LoginUser) authenticate.getPrincipal();  
31 - return user; 30 +// Authentication authenticate = authenticationManager.authenticate(token);
  31 +// SecurityContextHolder.getContext().setAuthentication(authenticate);
  32 + SecurityContextHolder.getContext().setAuthentication(token);
  33 +
  34 +
  35 +// LoginUser user = (LoginUser) authenticate.getPrincipal();
  36 + User user = new User();
  37 + user.setUsername(username);
  38 + LoginUser loginUser = new LoginUser(user, LocalDateTime.now());
  39 + return loginUser;
32 } 40 }
33 41
34 /** 42 /**
@@ -49,8 +57,13 @@ public class SecurityUtils { @@ -49,8 +57,13 @@ public class SecurityUtils {
49 if(authentication!=null){ 57 if(authentication!=null){
50 Object principal = authentication.getPrincipal(); 58 Object principal = authentication.getPrincipal();
51 if(principal!=null && !"anonymousUser".equals(principal)){ 59 if(principal!=null && !"anonymousUser".equals(principal)){
52 - LoginUser user = (LoginUser) authentication.getPrincipal();  
53 - return user; 60 +// LoginUser user = (LoginUser) authentication.getPrincipal();
  61 +
  62 + String username = (String) principal;
  63 + User user = new User();
  64 + user.setUsername(username);
  65 + LoginUser loginUser = new LoginUser(user, LocalDateTime.now());
  66 + return loginUser;
54 } 67 }
55 } 68 }
56 return null; 69 return null;
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
@@ -15,7 +15,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -15,7 +15,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
15 import org.springframework.security.config.annotation.web.builders.WebSecurity; 15 import org.springframework.security.config.annotation.web.builders.WebSecurity;
16 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 16 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
17 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 17 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  18 +import org.springframework.security.config.http.SessionCreationPolicy;
18 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 19 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  20 +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
19 21
20 import java.util.List; 22 import java.util.List;
21 23
@@ -56,22 +58,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -56,22 +58,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
56 */ 58 */
57 @Autowired 59 @Autowired
58 private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint; 60 private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint;
59 -// /**  
60 -// * 超时处理  
61 -// */  
62 -// @Autowired  
63 -// private InvalidSessionHandler invalidSessionHandler;  
64 -  
65 -// /**  
66 -// * 顶号处理  
67 -// */  
68 -// @Autowired  
69 -// private SessionInformationExpiredHandler sessionInformationExpiredHandler;  
70 -// /**  
71 -// * 登录用户没有权限访问资源  
72 -// */  
73 -// @Autowired  
74 -// private LoginUserAccessDeniedHandler accessDeniedHandler; 61 + @Autowired
  62 + private JwtAuthenticationFilter jwtAuthenticationFilter;
  63 +
  64 +// @Bean
  65 +// JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
  66 +// JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
  67 +// return jwtAuthenticationFilter;
  68 +// }
75 69
76 70
77 /** 71 /**
@@ -126,35 +120,56 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -126,35 +120,56 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
126 120
127 @Override 121 @Override
128 protected void configure(HttpSecurity http) throws Exception { 122 protected void configure(HttpSecurity http) throws Exception {
129 - http.cors().and().csrf().disable();  
130 - // 设置允许添加静态文件  
131 - http.headers().contentTypeOptions().disable();  
132 - http.authorizeRequests()  
133 - // 放行接口 123 + http.headers().contentTypeOptions().disable()
  124 + .and().cors()
  125 + .and().csrf().disable()
  126 + .sessionManagement()
  127 + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  128 +
  129 + // 配置拦截规则
  130 + .and()
  131 + .authorizeRequests()
134 .antMatchers("/api/user/login","/index/hook/**").permitAll() 132 .antMatchers("/api/user/login","/index/hook/**").permitAll()
135 - // 除上面外的所有请求全部需要鉴权认证  
136 .anyRequest().authenticated() 133 .anyRequest().authenticated()
137 - // 异常处理(权限拒绝、登录失效等)  
138 - .and().exceptionHandling()  
139 - //匿名用户访问无权限资源时的异常处理 134 + // 异常处理器
  135 + .and()
  136 + .exceptionHandling()
140 .authenticationEntryPoint(anonymousAuthenticationEntryPoint) 137 .authenticationEntryPoint(anonymousAuthenticationEntryPoint)
141 -// .accessDeniedHandler(accessDeniedHandler)//登录用户没有权限访问资源  
142 - // 登入 允许所有用户  
143 - .and().formLogin().permitAll()  
144 - //登录成功处理逻辑  
145 - .successHandler(loginSuccessHandler)  
146 - //登录失败处理逻辑  
147 - .failureHandler(loginFailureHandler)  
148 - // 登出  
149 - .and().logout().logoutUrl("/api/user/logout").permitAll()  
150 - //登出成功处理逻辑  
151 - .logoutSuccessHandler(logoutHandler)  
152 - .deleteCookies("JSESSIONID")  
153 - // 会话管理  
154 -// .and().sessionManagement().invalidSessionStrategy(invalidSessionHandler) // 超时处理  
155 -// .maximumSessions(1)//同一账号同时登录最大用户数  
156 -// .expiredSessionStrategy(sessionInformationExpiredHandler) // 顶号处理 138 +// .accessDeniedHandler(jwtAccessDeniedHandler)
  139 + // 配置自定义的过滤器
  140 +// .and()
  141 +// .addFilter(jwtAuthenticationFilter)
  142 + // 验证码过滤器放在UsernamePassword过滤器之前
  143 +// .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
157 ; 144 ;
  145 + http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
  146 +// // 设置允许添加静态文件
  147 +// http.headers().contentTypeOptions().disable();
  148 +// http.authorizeRequests()
  149 +// // 放行接口
  150 +// .antMatchers("/api/user/login","/index/hook/**").permitAll()
  151 +// // 除上面外的所有请求全部需要鉴权认证
  152 +// .anyRequest().authenticated()
  153 +// // 禁用session
  154 +// .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  155 +// // 异常处理(权限拒绝、登录失效等)
  156 +// .and().exceptionHandling()
  157 +// // 匿名用户访问无权限资源时的异常处理
  158 +// .authenticationEntryPoint(anonymousAuthenticationEntryPoint)
  159 +// // 登录 允许所有用户
  160 +// .and().formLogin()
  161 +// // 登录成功处理逻辑 在这里给出JWT
  162 +// .successHandler(loginSuccessHandler)
  163 +// // 登录失败处理逻辑
  164 +// .failureHandler(loginFailureHandler)
  165 +// // 登出
  166 +// .and().logout().logoutUrl("/api/user/logout").permitAll()
  167 +// // 登出成功处理逻辑
  168 +// .logoutSuccessHandler(logoutHandler)
  169 +// // 配置自定义的过滤器
  170 +// .and()
  171 +// .addFilter(jwtAuthenticationFilter())
  172 +// ;
158 173
159 } 174 }
160 175
src/main/java/com/genersoft/iot/vmp/conf/security/dto/JwtUser.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.security.dto;
  2 +
  3 +public class JwtUser {
  4 +
  5 + public enum TokenStatus{
  6 + /**
  7 + * 正常的使用状态
  8 + */
  9 + NORMAL,
  10 + /**
  11 + * 过期而失效
  12 + */
  13 + EXPIRED,
  14 + /**
  15 + * 即将过期
  16 + */
  17 + EXPIRING_SOON,
  18 + /**
  19 + * 异常
  20 + */
  21 + EXCEPTION
  22 + }
  23 +
  24 + private String userName;
  25 +
  26 + private String password;
  27 +
  28 + private TokenStatus status;
  29 +
  30 + public String getUserName() {
  31 + return userName;
  32 + }
  33 +
  34 + public void setUserName(String userName) {
  35 + this.userName = userName;
  36 + }
  37 +
  38 + public TokenStatus getStatus() {
  39 + return status;
  40 + }
  41 +
  42 + public void setStatus(TokenStatus status) {
  43 + this.status = status;
  44 + }
  45 +
  46 + public String getPassword() {
  47 + return password;
  48 + }
  49 +
  50 + public void setPassword(String password) {
  51 + this.password = password;
  52 + }
  53 +}
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
1 package com.genersoft.iot.vmp.vmanager.user; 1 package com.genersoft.iot.vmp.vmanager.user;
2 2
3 import com.genersoft.iot.vmp.conf.exception.ControllerException; 3 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  4 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
4 import com.genersoft.iot.vmp.conf.security.SecurityUtils; 5 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
5 import com.genersoft.iot.vmp.conf.security.dto.LoginUser; 6 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
6 import com.genersoft.iot.vmp.service.IRoleService; 7 import com.genersoft.iot.vmp.service.IRoleService;
@@ -21,6 +22,8 @@ import org.springframework.util.ObjectUtils; @@ -21,6 +22,8 @@ import org.springframework.util.ObjectUtils;
21 import org.springframework.web.bind.annotation.*; 22 import org.springframework.web.bind.annotation.*;
22 23
23 import javax.security.sasl.AuthenticationException; 24 import javax.security.sasl.AuthenticationException;
  25 +import javax.servlet.http.HttpServletRequest;
  26 +import javax.servlet.http.HttpServletResponse;
24 import java.util.List; 27 import java.util.List;
25 28
26 @Tag(name = "用户管理") 29 @Tag(name = "用户管理")
@@ -43,7 +46,7 @@ public class UserController { @@ -43,7 +46,7 @@ public class UserController {
43 @Operation(summary = "登录") 46 @Operation(summary = "登录")
44 @Parameter(name = "username", description = "用户名", required = true) 47 @Parameter(name = "username", description = "用户名", required = true)
45 @Parameter(name = "password", description = "密码(32位md5加密)", required = true) 48 @Parameter(name = "password", description = "密码(32位md5加密)", required = true)
46 - public LoginUser login(@RequestParam String username, @RequestParam String password){ 49 + public LoginUser login(HttpServletRequest request, HttpServletResponse response, @RequestParam String username, @RequestParam String password){
47 LoginUser user = null; 50 LoginUser user = null;
48 try { 51 try {
49 user = SecurityUtils.login(username, password, authenticationManager); 52 user = SecurityUtils.login(username, password, authenticationManager);
@@ -52,6 +55,9 @@ public class UserController { @@ -52,6 +55,9 @@ public class UserController {
52 } 55 }
53 if (user == null) { 56 if (user == null) {
54 throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误"); 57 throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误");
  58 + }else {
  59 + String jwt = JwtUtils.createToken(username, password);
  60 + response.setHeader(JwtUtils.getHeader(), jwt);
55 } 61 }
56 return user; 62 return user;
57 } 63 }