Skip to content

Commit ee3ddfc

Browse files
committed
fix security bug
1 parent d12f537 commit ee3ddfc

File tree

4 files changed

+69
-56
lines changed

4 files changed

+69
-56
lines changed

springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/AutoConfiguration.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ public SecurityFilterChain filterChain(HttpSecurity security, Jwt jwt,SecurityLo
8282
.and()
8383
.authorizeHttpRequests(
8484
registry -> {
85-
registry.requestMatchers(properties.getAuthenticatedUrls()).authenticated()
85+
registry.requestMatchers(properties.getIgnoreUrls()).permitAll()
86+
.requestMatchers(properties.getAuthenticatedUrls()).authenticated()
8687
.anyRequest().permitAll();
8788
}
8889
)

springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/configurer/HttpSecurityConfigurer.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ public class HttpSecurityConfigurer extends AbstractHttpConfigurer<HttpSecurityC
1919
private final SecurityJwtProperties securityJwtProperties;
2020

2121
@Override
22-
public void configure(HttpSecurity http) throws Exception {
23-
AuthenticationManager manager = http.getSharedObject(AuthenticationManager.class);
24-
http.addFilter(new MyLoginFilter(manager, jwt,securityLoginHandler, securityJwtProperties));
25-
http.addFilter(new MyAuthenticationFilter(manager, jwt));
22+
public void configure(HttpSecurity security) throws Exception {
23+
AuthenticationManager manager = security.getSharedObject(AuthenticationManager.class);
24+
security.addFilter(new MyLoginFilter(manager, jwt,securityLoginHandler, securityJwtProperties));
25+
security.addFilter(new MyAuthenticationFilter(manager,securityJwtProperties,jwt));
2626
}
2727
}

springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java

+34-44
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,21 @@
55
import com.codingapi.springboot.security.exception.TokenExpiredException;
66
import com.codingapi.springboot.security.jwt.Jwt;
77
import com.codingapi.springboot.security.jwt.Token;
8+
import com.codingapi.springboot.security.properties.SecurityJwtProperties;
89
import jakarta.servlet.FilterChain;
910
import jakarta.servlet.ServletException;
1011
import jakarta.servlet.http.HttpServletRequest;
1112
import jakarta.servlet.http.HttpServletResponse;
1213
import lombok.extern.slf4j.Slf4j;
1314
import org.apache.commons.io.IOUtils;
14-
import org.springframework.security.authentication.AuthenticationDetailsSource;
1515
import org.springframework.security.authentication.AuthenticationManager;
16-
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
1716
import org.springframework.security.core.context.SecurityContextHolder;
18-
import org.springframework.security.web.authentication.www.BasicAuthenticationConverter;
1917
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
20-
import org.springframework.util.Assert;
18+
import org.springframework.util.AntPathMatcher;
2119
import org.springframework.util.StringUtils;
20+
import org.springframework.web.filter.OncePerRequestFilter;
2221

2322
import java.io.IOException;
24-
import java.nio.charset.Charset;
2523
import java.nio.charset.StandardCharsets;
2624

2725
@Slf4j
@@ -31,54 +29,44 @@ public class MyAuthenticationFilter extends BasicAuthenticationFilter {
3129

3230
private final Jwt jwt;
3331

34-
private final BasicAuthenticationConverter authenticationConverter = new BasicAuthenticationConverter();
32+
private final SecurityJwtProperties securityJwtProperties;
33+
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
3534

36-
public MyAuthenticationFilter(AuthenticationManager authenticationManager, Jwt jwt) {
37-
super(authenticationManager);
35+
public MyAuthenticationFilter(AuthenticationManager manager, SecurityJwtProperties securityJwtProperties, Jwt jwt) {
36+
super(manager);
3837
this.jwt = jwt;
38+
this.securityJwtProperties = securityJwtProperties;
3939
}
4040

41-
public void setAuthenticationDetailsSource(AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
42-
this.authenticationConverter.setAuthenticationDetailsSource(authenticationDetailsSource);
43-
}
44-
45-
public void setCredentialsCharset(String credentialsCharset) {
46-
Assert.hasText(credentialsCharset, "credentialsCharset cannot be null or empty");
47-
this.authenticationConverter.setCredentialsCharset(Charset.forName(credentialsCharset));
48-
}
4941

5042
@Override
5143
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
5244
log.debug("token authentication ~");
53-
54-
UsernamePasswordAuthenticationToken authRequest = authenticationConverter.convert(request);
55-
if (authRequest == null) {
56-
this.logger.trace("Did not process authentication request since failed to find username and password in Basic Authorization header");
57-
chain.doFilter(request, response);
58-
return;
45+
for (String antUrl : securityJwtProperties.getAuthenticatedUrls()) {
46+
if(antPathMatcher.match(antUrl,request.getRequestURI())) {
47+
48+
String sign = request.getHeader(TOKEN_KEY);
49+
if (!StringUtils.hasLength(sign)) {
50+
writeResponse(response, Response.buildFailure("token.error", "token must not null."));
51+
return;
52+
}
53+
54+
Token token = jwt.parser(sign);
55+
if (token.canRestToken()) {
56+
Token newSign = jwt.create(token.getUsername(), token.decodeIv(), token.getAuthorities(), token.getExtra());
57+
log.info("reset token ");
58+
response.setHeader(TOKEN_KEY, newSign.getToken());
59+
}
60+
try {
61+
token.verify();
62+
} catch (TokenExpiredException e) {
63+
writeResponse(response, Response.buildFailure("token.expire", "token expire."));
64+
return;
65+
}
66+
67+
SecurityContextHolder.getContext().setAuthentication(token.getAuthenticationToken());
68+
}
5969
}
60-
61-
String sign = request.getHeader(TOKEN_KEY);
62-
if (!StringUtils.hasLength(sign)) {
63-
writeResponse(response, Response.buildFailure("token.error", "token must not null."));
64-
return;
65-
}
66-
67-
Token token = jwt.parser(sign);
68-
if (token.canRestToken()) {
69-
Token newSign = jwt.create(token.getUsername(), token.decodeIv(), token.getAuthorities(),token.getExtra());
70-
log.info("reset token ");
71-
response.setHeader(TOKEN_KEY, newSign.getToken());
72-
}
73-
try {
74-
token.verify();
75-
} catch (TokenExpiredException e) {
76-
writeResponse(response, Response.buildFailure("token.expire", "token expire."));
77-
return;
78-
}
79-
80-
SecurityContextHolder.getContext().setAuthentication(token.getAuthenticationToken());
81-
8270
chain.doFilter(request, response);
8371

8472
}
@@ -87,4 +75,6 @@ private void writeResponse(HttpServletResponse servletResponse, Response returnR
8775
String content = JSONObject.toJSONString(returnResponse);
8876
IOUtils.write(content, servletResponse.getOutputStream(), StandardCharsets.UTF_8);
8977
}
78+
79+
9080
}

springboot-starter-security-jwt/src/test/java/com/codingapi/springboot/security/SecurityJwtApplicationTest.java

+29-7
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,40 @@ void login() throws Exception {
3232
JSONObject json = new JSONObject();
3333
json.put("username","admin");
3434
json.put("password","123456");
35-
mockMvc.perform(post("/user/login").content(json.toJSONString().getBytes(StandardCharsets.UTF_8)).contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
35+
mockMvc.perform(post("/user/login")
36+
.content(json.toJSONString().getBytes(StandardCharsets.UTF_8))
37+
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
3638
}
3739

3840
@Test
3941
void noToken() throws Exception {
40-
mockMvc.perform(get("/api/hello").contentType(MediaType.APPLICATION_JSON)).andExpect(result -> {
42+
mockMvc.perform(get("/api/hello")
43+
.contentType(MediaType.APPLICATION_JSON)).andExpect(result -> {
4144
String body = result.getResponse().getContentAsString();
4245
JSONObject jsonObject = JSONObject.parseObject(body);
4346
log.info("body:{}",jsonObject);
4447
assertEquals(jsonObject.getString("errCode"),"token.error","token authentication error");
4548
});
4649
}
4750

51+
@Test
52+
void random() throws Exception {
53+
mockMvc.perform(get("/xxx/hello")
54+
.contentType(MediaType.APPLICATION_JSON))
55+
.andExpect(result -> {
56+
assertEquals(404,result.getResponse().getStatus());
57+
});
58+
}
59+
4860
@Test
4961
void haveToken() throws Exception {
5062

5163
JSONObject json = new JSONObject();
5264
json.put("username","admin");
5365
json.put("password","123456");
54-
MvcResult mvcResult = mockMvc.perform(post("/user/login").content(json.toJSONString().getBytes(StandardCharsets.UTF_8)).contentType(MediaType.APPLICATION_JSON)).andReturn();
66+
MvcResult mvcResult = mockMvc.perform(post("/user/login")
67+
.content(json.toJSONString().getBytes(StandardCharsets.UTF_8))
68+
.contentType(MediaType.APPLICATION_JSON)).andReturn();
5569
JSONObject loginData = JSONObject.parseObject(mvcResult.getResponse().getContentAsString());
5670

5771
mockMvc.perform(get("/api/hello").header("Authorization",loginData.getJSONObject("data").getString("token")).contentType(MediaType.APPLICATION_JSON)).andExpect(result -> {
@@ -67,12 +81,16 @@ void resetToken() throws Exception {
6781
JSONObject json = new JSONObject();
6882
json.put("username","admin");
6983
json.put("password","123456");
70-
MvcResult mvcResult = mockMvc.perform(post("/user/login").content(json.toJSONString().getBytes(StandardCharsets.UTF_8)).contentType(MediaType.APPLICATION_JSON)).andReturn();
84+
MvcResult mvcResult = mockMvc.perform(post("/user/login")
85+
.content(json.toJSONString().getBytes(StandardCharsets.UTF_8))
86+
.contentType(MediaType.APPLICATION_JSON)).andReturn();
7187
JSONObject loginData = JSONObject.parseObject(mvcResult.getResponse().getContentAsString());
7288

7389
Thread.sleep(1000*5);
7490

75-
mockMvc.perform(get("/api/hello").header("Authorization",loginData.getJSONObject("data").getString("token")).contentType(MediaType.APPLICATION_JSON)).andExpect(result -> {
91+
mockMvc.perform(get("/api/hello")
92+
.header("Authorization",loginData.getJSONObject("data").getString("token"))
93+
.contentType(MediaType.APPLICATION_JSON)).andExpect(result -> {
7694
String body = result.getResponse().getContentAsString();
7795
String newToken = result.getResponse().getHeader("Authorization");
7896

@@ -87,12 +105,16 @@ void expireToken() throws Exception {
87105
JSONObject json = new JSONObject();
88106
json.put("username","admin");
89107
json.put("password","123456");
90-
MvcResult mvcResult = mockMvc.perform(post("/user/login").content(json.toJSONString().getBytes(StandardCharsets.UTF_8)).contentType(MediaType.APPLICATION_JSON)).andReturn();
108+
MvcResult mvcResult = mockMvc.perform(post("/user/login")
109+
.content(json.toJSONString().getBytes(StandardCharsets.UTF_8))
110+
.contentType(MediaType.APPLICATION_JSON)).andReturn();
91111
JSONObject loginData = JSONObject.parseObject(mvcResult.getResponse().getContentAsString());
92112

93113
Thread.sleep(1000*10);
94114

95-
mockMvc.perform(get("/api/hello").header("Authorization",loginData.getJSONObject("data").getString("token")).contentType(MediaType.APPLICATION_JSON)).andExpect(result -> {
115+
mockMvc.perform(get("/api/hello")
116+
.header("Authorization",loginData.getJSONObject("data").getString("token"))
117+
.contentType(MediaType.APPLICATION_JSON)).andExpect(result -> {
96118
String body = result.getResponse().getContentAsString();
97119
JSONObject data = JSONObject.parseObject(body);
98120
assertEquals(data.getString("errCode"),"token.expire","token authentication error");

0 commit comments

Comments
 (0)