diff --git a/pom.xml b/pom.xml index fff0aec..1b4bc17 100644 --- a/pom.xml +++ b/pom.xml @@ -18,12 +18,12 @@ 21 + - io.jsonwebtoken jjwt diff --git a/src/main/java/com/example/demo/DemoApplication.java b/src/main/java/com/example/demo/DemoApplication.java index b9bb538..8d3e628 100644 --- a/src/main/java/com/example/demo/DemoApplication.java +++ b/src/main/java/com/example/demo/DemoApplication.java @@ -2,7 +2,6 @@ package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; @SpringBootApplication diff --git a/src/main/java/com/example/demo/Util/JWTUtil.java b/src/main/java/com/example/demo/Util/JWTUtil.java index 7fdda9d..1dfea3e 100644 --- a/src/main/java/com/example/demo/Util/JWTUtil.java +++ b/src/main/java/com/example/demo/Util/JWTUtil.java @@ -1,13 +1,16 @@ package com.example.demo.Util; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; + import org.springframework.security.core.userdetails.UserDetails; + import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; @@ -35,6 +38,7 @@ public class JWTUtil { * @param user * @return */ + public static String createJWT(UserDetails user) { ObjectMapper mapper = new ObjectMapper(); try { @@ -134,6 +138,7 @@ public class JWTUtil { */ public static Claims parseJWT(String jwt) throws Exception { SecretKey secretKey = generalKey(); + System.out.println(jwt+"-----------------------++++++++++++++++++++++-"); return Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(jwt) diff --git a/src/main/java/com/example/demo/Util/ReplaceStreamFilter.java b/src/main/java/com/example/demo/Util/ReplaceStreamFilter.java new file mode 100644 index 0000000..3c3e595 --- /dev/null +++ b/src/main/java/com/example/demo/Util/ReplaceStreamFilter.java @@ -0,0 +1,27 @@ +package com.example.demo.Util; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +//替换HttpServletRequest +@Slf4j +public class ReplaceStreamFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + log.info("StreamFilter初始化..."); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + ServletRequest requestWrapper = new RequestWrapper((HttpServletRequest) request); + chain.doFilter(requestWrapper, response); + } + + @Override + public void destroy() { + log.info("StreamFilter销毁..."); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/Util/RequestWrapper.java b/src/main/java/com/example/demo/Util/RequestWrapper.java new file mode 100644 index 0000000..e9b1f63 --- /dev/null +++ b/src/main/java/com/example/demo/Util/RequestWrapper.java @@ -0,0 +1,123 @@ +package com.example.demo.Util; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import lombok.extern.slf4j.Slf4j; + + +import java.io.*; +import java.nio.charset.Charset; + + +//包装HttpServletRequest,目的是让其输入流可重复读 +@Slf4j +public class RequestWrapper extends HttpServletRequestWrapper { + /** + * 存储body数据的容器 + */ + private final byte[] body; + + public RequestWrapper(HttpServletRequest request) throws IOException { + super(request); + + // 将body数据存储起来 + String bodyStr = getBodyString(request); + body = bodyStr.getBytes(Charset.defaultCharset()); + System.out.println(new String(body, Charset.defaultCharset()) + "+**+*+*+*++*+*+*+"); + + + } + + /** + * 获取请求Body + * + * @param request request + * @return String + */ + public String getBodyString(final ServletRequest request) { + try { + return inputStream2String(request.getInputStream()); + } catch (IOException e) { + log.error("", e); + throw new RuntimeException(e); + } + } + + /** + * 获取请求Body + * + * @return String + */ + public String getBodyString() { + final InputStream inputStream = new ByteArrayInputStream(body); + + return inputStream2String(inputStream); + } + + /** + * 将inputStream里的数据读取出来并转换成字符串 + * + * @param inputStream inputStream + * @return String + */ + private String inputStream2String(InputStream inputStream) { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + + try { + reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset())); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + log.error("", e); + throw new RuntimeException(e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + log.error("", e); + } + } + } + + return sb.toString(); + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + + final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); + + return new ServletInputStream() { + @Override + public int read() throws IOException { + return inputStream.read(); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/Util/TokenPayload.java b/src/main/java/com/example/demo/Util/TokenPayload.java new file mode 100644 index 0000000..4b97ade --- /dev/null +++ b/src/main/java/com/example/demo/Util/TokenPayload.java @@ -0,0 +1,18 @@ +package com.example.demo.Util; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +@Data +public class TokenPayload { + @Setter + @Getter + @JsonProperty("token") + private String token; + private String jwcode; + private String password; +} + diff --git a/src/main/java/com/example/demo/controller/AdminController.java b/src/main/java/com/example/demo/controller/AdminController.java index c85892d..82e7a62 100644 --- a/src/main/java/com/example/demo/controller/AdminController.java +++ b/src/main/java/com/example/demo/controller/AdminController.java @@ -1,7 +1,4 @@ package com.example.demo.controller; - - - import com.example.demo.Util.JWTUtil; import com.example.demo.domain.entity.Admin; import com.example.demo.domain.vo.Page; @@ -38,8 +35,11 @@ public class AdminController { public Result login(@RequestBody Admin admin){ try { + System.out.println(admin+"*-*-*-*-*-*-*-*-*-*-1"); admin = adminService.login(admin); + System.out.println(admin+"*-*-*-*-*-*-*-*-*-*-"); String token = JWTUtil.createJWT(admin); + System.out.println(token+"token----------------------------------------"); admin.setPassword(null); return Result.success(token,admin); } catch (Exception e) { diff --git a/src/main/java/com/example/demo/domain/entity/Admin.java b/src/main/java/com/example/demo/domain/entity/Admin.java index f2be10f..b372bb1 100644 --- a/src/main/java/com/example/demo/domain/entity/Admin.java +++ b/src/main/java/com/example/demo/domain/entity/Admin.java @@ -25,7 +25,7 @@ public class Admin implements UserDetails, Serializable { @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd") private Date createTime; - + private String jwcode; @Override @JsonIgnore public Collection getAuthorities() { diff --git a/src/main/java/com/example/demo/mapper/AdminMapper.java b/src/main/java/com/example/demo/mapper/AdminMapper.java index 776bc21..a443c2f 100644 --- a/src/main/java/com/example/demo/mapper/AdminMapper.java +++ b/src/main/java/com/example/demo/mapper/AdminMapper.java @@ -11,9 +11,9 @@ import java.util.List; public interface AdminMapper { @Insert({ "insert into admin", - "(name,username,password,permission,area,admin_flag,create_time)", + "(name,jwcode,password,permission,area,admin_flag,create_time)", "values", - "(#{name},#{username},,#{password},#{permission},#{area},#{admin_flag},now())" + "(#{name},#{jwcode},,#{password},#{permission},#{area},#{admin_flag},now())" }) @Options(useGeneratedKeys = true,keyColumn = "admin_id",keyProperty = "adminId") int insert(Admin admin); @@ -23,7 +23,7 @@ public interface AdminMapper { "UPDATE admin", "", "name =#{name},", - "username =#{username},", + "jwcode =#{jwcode},", "password =#{password},", "permission =#{permission},", "area =#{area},", @@ -39,7 +39,7 @@ public interface AdminMapper { Admin selectById(Integer adminId); @Select({ "select * from admin", - "where username=#{username}" + "where jwcode=#{jwcode}" }) Admin selectByName(String username); @Select({ @@ -47,7 +47,7 @@ public interface AdminMapper { "SELECT * from admin", "", " and `name` like concat('%',#{name},'%'),", - " and `username` like concat('%',#{username},'%'),", + " and `jwcode` like concat('%',#{jwcode},'%'),", " and permission=#{permission},", " and `area` like concat('%',#{area},'%'),", " and admin_flag =#{adminFlag},", diff --git a/src/main/java/com/example/demo/security/SecurityConfig.java b/src/main/java/com/example/demo/security/SecurityConfig.java index 8214363..aff3e1d 100644 --- a/src/main/java/com/example/demo/security/SecurityConfig.java +++ b/src/main/java/com/example/demo/security/SecurityConfig.java @@ -56,12 +56,7 @@ public class SecurityConfig { .exceptionHandling( exception -> exception.accessDeniedHandler(accessDeniedHandler())) // 配置路径拦截 .authorizeHttpRequests( request -> - request.requestMatchers( HttpMethod.GET, - // 用户不登录可以访问的路径 - "/captcha", - "/category", - "/product/**", - "/upload/**").permitAll() + request .requestMatchers( HttpMethod.POST, // 用户不登录就可以访问的路径 "/user/login", "/user", diff --git a/src/main/java/com/example/demo/security/TokenFilter.java b/src/main/java/com/example/demo/security/TokenFilter.java index c305359..f5c5dce 100644 --- a/src/main/java/com/example/demo/security/TokenFilter.java +++ b/src/main/java/com/example/demo/security/TokenFilter.java @@ -1,53 +1,113 @@ +//package com.example.demo.security; +// +// +//import com.example.demo.Util.JWTUtil; +//import com.example.demo.Util.RequestWrapper; +//import com.example.demo.domain.entity.Admin; +//import jakarta.servlet.FilterChain; +//import jakarta.servlet.ServletException; +//import jakarta.servlet.http.HttpServletRequest; +//import jakarta.servlet.http.HttpServletResponse; +//import org.springframework.core.annotation.Order; +//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +//import org.springframework.security.core.context.SecurityContextHolder; +//import org.springframework.security.core.userdetails.UserDetails; +//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +//import org.springframework.stereotype.Component; +//import org.springframework.util.ObjectUtils; +//import org.springframework.util.StringUtils; +//import org.springframework.web.filter.OncePerRequestFilter; +//import java.io.IOException; +// +// +//@Component +//public class TokenFilter extends OncePerRequestFilter { +// @Override +// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { +// // 取Token 生成登录信息 +//// String token = request.getHeader("token"); +// String token = new RequestWrapper(request).getBodyString(); +// +// System.out.println(token+"123132132"); +// +// // token不为空 +// if (StringUtils.hasText(token)){ +// try { +// UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class); +// if ( ! ObjectUtils.isEmpty(userDetails)) { +// // 将这个用户注册到Security中 +// UsernamePasswordAuthenticationToken authenticationToken +// = new UsernamePasswordAuthenticationToken( +// userDetails, null, +// userDetails.getAuthorities()); +// authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); +// SecurityContextHolder.getContext().setAuthentication(authenticationToken); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// // Token无效, +// } +// } +// // 过滤器放行 +// filterChain.doFilter(request, response); +// } +//} package com.example.demo.security; - - import com.example.demo.Util.JWTUtil; +import com.example.demo.Util.TokenPayload; import com.example.demo.domain.entity.Admin; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; - import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; - import java.io.IOException; +import java.io.InputStream; @Component public class TokenFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - // 取Token 生成登录信息 - String token = request.getHeader("token"); - // token不为空 - if (StringUtils.hasText(token)){ - // jwt解密 - try { - UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class); - if ( ! ObjectUtils.isEmpty(userDetails)) { - // 将这个用户注册到Security中 - UsernamePasswordAuthenticationToken authenticationToken + // 确保请求体只被读取一次 + boolean hasRequestBody = "POST".equals(request.getMethod()); + if (hasRequestBody) { + // 获取输入流 + try (InputStream inputStream = request.getInputStream()) { + // 使用Jackson ObjectMapper解析JSON + ObjectMapper objectMapper = new ObjectMapper(); + TokenPayload tokenPayload = objectMapper.readValue(inputStream, TokenPayload.class); - = new UsernamePasswordAuthenticationToken( - userDetails, null, - userDetails.getAuthorities()); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authenticationToken); + // 检查tokenPayload中是否存在token属性,并且这个属性不为空 + String token = tokenPayload.getToken(); + if (StringUtils.hasText(token)) { + try { + UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class); + if (!ObjectUtils.isEmpty(userDetails)) { + // 将这个用户注册到Security中 + UsernamePasswordAuthenticationToken authenticationToken + = new UsernamePasswordAuthenticationToken( + userDetails, null, + userDetails.getAuthorities()); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + } catch (Exception e) { + e.printStackTrace(); + // Token无效,可以在这里添加相应的处理逻辑,例如返回401状态码等 + } } - } catch (Exception e) { - e.printStackTrace(); - // Token无效, } } // 过滤器放行 filterChain.doFilter(request, response); } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java b/src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java index 3e35cf1..7e5ca60 100644 --- a/src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java +++ b/src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java @@ -67,12 +67,16 @@ public class AdminServiceImpl implements AdminService { @Override public Admin login(Admin admin) throws Exception { + System.out.println("第一步"); UsernamePasswordAuthenticationToken token = - new UsernamePasswordAuthenticationToken(admin.getUsername(),admin.getPassword()); + new UsernamePasswordAuthenticationToken(admin.getJwcode(),admin.getPassword()); + System.out.println(token+"第二步"); try { Authentication authentication = authenticationManager.authenticate(token); + System.out.println(authentication+"第一步"); Admin loginAdmin = (Admin) authentication.getPrincipal(); - + System.out.println(token); + System.out.println(loginAdmin+"logAdmin"); return loginAdmin; }catch (BadCredentialsException exception){ throw new BadCredentialsException("用户或密码错误"); diff --git a/src/main/java/com/example/demo/sevice/AdminService.java b/src/main/java/com/example/demo/sevice/AdminService.java index d319237..78b78b3 100644 --- a/src/main/java/com/example/demo/sevice/AdminService.java +++ b/src/main/java/com/example/demo/sevice/AdminService.java @@ -10,7 +10,7 @@ public interface AdminService { int add(Admin admin); int edit(Admin admin); Admin findById(Integer adminId); - Admin findByUsername(String username); + Admin findByUsername(String jwcode); List search(Admin admin); PageInfo searchForPage(Integer pageNum, Integer pageSize, Admin admin); Admin login(Admin admin)throws Exception;