添加登录测试

This commit is contained in:
Bunny 2025-07-10 17:14:32 +08:00
parent 46ed909158
commit 44dee07956
11 changed files with 167 additions and 15 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.3</version>
<version>3.3.13</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.mall</groupId>

View File

@ -12,7 +12,6 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@ -26,10 +25,10 @@ public class DefaultSecurityConfig {
*/
@Bean
@ConditionalOnMissingBean(UserDetailsService.class)
InMemoryUserDetailsManager inMemoryUserDetailsManager() {
String generatedPassword = PasswordEncoderFactories.createDelegatingPasswordEncoder()
.encode("123456");
return new InMemoryUserDetailsManager(User.withUsername("user")
InMemoryUserDetailsManager inMemoryUserDetailsManager(PasswordEncoder passwordEncoder) {
String generatedPassword = passwordEncoder.encode("123456");
return new InMemoryUserDetailsManager(User.withUsername("bunny")
.password(generatedPassword).roles("USER").build());
}
@ -46,7 +45,8 @@ public class DefaultSecurityConfig {
@Bean
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(userDetailsService);
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder);
return new ProviderManager(authenticationProvider);

View File

@ -41,4 +41,14 @@ public class Knife4jConfig {
public GroupedOpenApi all() {
return GroupedOpenApi.builder().group("全部请求接口").pathsToMatch("/api/**").build();
}
@Bean
public GroupedOpenApi system() {
return GroupedOpenApi.builder().group("系统请求接口").pathsToMatch("/api/system/**").build();
}
@Bean
public GroupedOpenApi security() {
return GroupedOpenApi.builder().group("security接口").pathsToMatch("/api/security/**").build();
}
}

View File

@ -1,13 +1,19 @@
package com.spring.config;
import com.spring.config.handler.SecurityAccessDeniedHandler;
import com.spring.config.handler.SecurityAuthenticationEntryPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import javax.sql.DataSource;
@EnableWebSecurity
@Configuration
public class SecurityConfiguration {
@ -15,11 +21,29 @@ public class SecurityConfiguration {
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
http
.httpBasic(Customizer.withDefaults())
.requestCache(cache -> cache.requestCache(requestCache))
// 如果禁用登录页会有弹窗形式的登录
.formLogin(AbstractHttpConfigurer::disable)
// 开启打开默认页会让登录
// .formLogin(Customizer.withDefaults())
.formLogin(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers("/", "/*/*/login").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(configurer -> {
// 访问拒绝处理器
configurer.accessDeniedHandler(new SecurityAccessDeniedHandler());
// 认证入口点
configurer.authenticationEntryPoint(new SecurityAuthenticationEntryPoint());
})
;
return http.build();
}
@Bean
public UserDetailsService userDetailsService(DataSource dataSource) {
return new JdbcUserDetailsManager(dataSource);
}
}

View File

@ -0,0 +1,28 @@
package com.spring.config.handler;
import com.alibaba.fastjson2.JSON;
import com.spring.domain.vo.result.Result;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import java.io.IOException;
@Slf4j
public class SecurityAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
log.error("CustomerAccessDeniedHandler:{}", accessDeniedException.getLocalizedMessage());
Result<Object> result = Result.error(accessDeniedException.getMessage());
Object json = JSON.toJSON(result);
// 返回响应
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}

View File

@ -0,0 +1,29 @@
package com.spring.config.handler;
import com.alibaba.fastjson2.JSON;
import com.spring.domain.vo.result.Result;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import java.io.IOException;
@Slf4j
public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
log.error("CustomerAccessDeniedHandler:{}", authException.getLocalizedMessage());
Result<Object> result = Result.error(authException.getMessage());
Object json = JSON.toJSON(result);
// 返回响应
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
}
}

View File

@ -0,0 +1,35 @@
package com.spring.controller.security;
import com.spring.domain.dto.security.LoginRequest;
import com.spring.domain.vo.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "Login接口", description = "登录接口")
@RestController
@RequestMapping("/api/security")
@RequiredArgsConstructor
public class LoginController {
private final AuthenticationManager authenticationManager;
@Operation(summary = "登录接口", description = "系统登录接口")
@PostMapping("login")
public Result<Authentication> login(@RequestBody LoginRequest loginRequest) {
String username = loginRequest.getUsername();
String password = loginRequest.getPassword();
Authentication authenticationRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
Authentication authenticationResponse = authenticationManager.authenticate(authenticationRequest);
return Result.success(authenticationResponse);
}
}

View File

@ -33,7 +33,7 @@ public class MessageReceivedController {
private final MessageReceivedService messageReceivedService;
@Operation(summary = "分页查询", description = "分页")
@Operation(summary = "消息接受分页查询", description = "消息接受分页")
@GetMapping("{page}/{limit}")
public Result<PageResult<MessageReceivedVo>> getMessageReceivedPage(
@Parameter(name = "page", description = "当前页", required = true)
@ -46,21 +46,21 @@ public class MessageReceivedController {
return Result.success(pageResult);
}
@Operation(summary = "添加", description = "添加")
@Operation(summary = "添加", description = "添加消息接受")
@PostMapping()
public Result<String> addMessageReceived(@Valid @RequestBody MessageReceivedDto dto) {
messageReceivedService.addMessageReceived(dto);
return Result.success(ResultCodeEnum.ADD_SUCCESS);
}
@Operation(summary = "更新", description = "更新")
@Operation(summary = "更新", description = "更新消息接受")
@PutMapping()
public Result<String> updateMessageReceived(@Valid @RequestBody MessageReceivedDto dto) {
messageReceivedService.updateMessageReceived(dto);
return Result.success(ResultCodeEnum.UPDATE_SUCCESS);
}
@Operation(summary = "删除", description = "删除")
@Operation(summary = "删除", description = "删除消息接受")
@DeleteMapping()
public Result<String> deleteMessageReceived(@RequestBody List<Long> ids) {
messageReceivedService.deleteMessageReceived(ids);

View File

@ -0,0 +1,22 @@
package com.spring.domain.dto.security;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "LoginRequest", title = "LoginRequest登录参数", description = "登录请求参数")
public class LoginRequest {
@Schema(name = "username", title = "用户名")
private String username;
@Schema(name = "password", description = "密码")
private String password;
}

View File

@ -0,0 +1,4 @@
package com.spring.service.security;
public interface LoginService {
}

View File

@ -395,7 +395,7 @@
<p>学习最强大的Java安全框架保护您的应用程序免受现代安全威胁。Spring Security
6提供了全面的身份验证和授权功能让您的应用安全无忧。</p>
<div>
<a class="btn" href="#docs" target="_blank">开始学习</a>
<a class="btn" href="#docs">开始学习</a>
<a class="btn btn-outline" href="/doc.html" target="_blank">查看API文档</a>
</div>
</div>