@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
private final LoginService loginService;
private final JwtService jwtService;
private final AdminRepository adminRepository;
private final ObjectMapper objectMapper;
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(cs -> cs.disable())
.sessionManagement(s->s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.formLogin(f->f.disable())
.httpBasic(h->h.disable());
http
.authorizeHttpRequests(auth->{
//// auth.requestMatchers("/lectures/**").hasAnyRole("MANAGER")
//// auth.requestMatchers("/instructors/**").hasAnyRole("MANAGER")
// auth.requestMatchers("/instructors/**").authenticated()
// .requestMatchers("/lectures/**").permitAll()
//// .requestMatchers("/instructors/**").hasAnyRole("MANAGER")
// .requestMatchers("/admins/**").permitAll()
// .requestMatchers("/login").permitAll()
//auth.requestMatchers("/instructors/**").hasRole("MANAGER")
auth.anyRequest().permitAll()
;
});
return http.build();
}
@Bean
public AuthenticationManager authenticationManager() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(passwordEncoder());
provider.setUserDetailsService(loginService);
return new ProviderManager(provider);
}
@Bean
public LoginSuccessHandler loginSuccessHandler() {
return new LoginSuccessHandler(jwtService, adminRepository);
}
@Bean
public LoginFailureHandler loginFailureHandler() {
return new LoginFailureHandler();
}
@Bean
public CustomJsonUsernamePasswordAuthenticationFilter customJsonUsernamePasswordAuthenticationFilter() {
CustomJsonUsernamePasswordAuthenticationFilter customJsonUsernamePasswordLoginFilter
= new CustomJsonUsernamePasswordAuthenticationFilter(objectMapper);
customJsonUsernamePasswordLoginFilter.setAuthenticationManager(authenticationManager());
customJsonUsernamePasswordLoginFilter.setAuthenticationSuccessHandler(loginSuccessHandler());
customJsonUsernamePasswordLoginFilter.setAuthenticationFailureHandler(loginFailureHandler());
return customJsonUsernamePasswordLoginFilter;
}
@Bean
public JwtAuthenticationProcessingFilter jwtAuthenticationProcessingFilter() {
JwtAuthenticationProcessingFilter jwtAuthenticationFilter = new JwtAuthenticationProcessingFilter(jwtService, adminRepository);
return jwtAuthenticationFilter;
}
}
x
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationProcessingFilter extends OncePerRequestFilter {
private static final String NO_CHECK_URL = "/login";
private final JwtService jwtService;
private final AdminRepository adminRepository;
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (request.getRequestURI().equals(NO_CHECK_URL)) {
filterChain.doFilter(request, response);
return;
}
String refreshToken = jwtService.extractRefreshToken(request)
.filter(jwtService::isTokenValid)
.orElse(null);
if (refreshToken != null) {
checkRefreshTokenAndReIssueAccessToken(response, refreshToken);
return;
}
if (refreshToken == null) {
checkAccessTokenAndAuthentication(request, response, filterChain);
}
}
public void checkRefreshTokenAndReIssueAccessToken(HttpServletResponse response, String refreshToken) {
adminRepository.findByRefreshToken(refreshToken)
.ifPresent(admin -> {
String reIssuedRefreshToken = reIssueRefreshToken(admin);
jwtService.sendAccessAndRefreshToken(response, jwtService.createAccessToken(admin.getEmail()),
reIssuedRefreshToken);
});
}
private String reIssueRefreshToken(Admin admin) {
String reIssuedRefreshToken = jwtService.createRefreshToken();
admin.updateRefreshToken(reIssuedRefreshToken);
adminRepository.saveAndFlush(admin);
return reIssuedRefreshToken;
}
public void checkAccessTokenAndAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
log.info("checkAccessTokenAndAuthentication() 호출");
jwtService.extractAccessToken(request)
.filter(jwtService::isTokenValid)
.ifPresent(accessToken -> jwtService.extractEmail(accessToken)
.ifPresent(email -> adminRepository.findByEmail(email)
.ifPresent(this::saveAuthentication)));
log.info("saveAuthentication() 호출");
filterChain.doFilter(request, response);
}
public void saveAuthentication(Admin myAdmin) {
String password = myAdmin.getPassword();
UserDetails userDetailsUser = org.springframework.security.core.userdetails.User.builder()
.username(myAdmin.getEmail())
.password(password)
.roles(myAdmin.getRole().name())
.build();
Authentication authentication =
new UsernamePasswordAuthenticationToken(userDetailsUser, null,
authoritiesMapper.mapAuthorities(userDetailsUser.getAuthorities()));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
@RequiredArgsConstructor
@RequestMapping("/instructors")
@RestController
public class InstructorController {
private final InstructorService instructorService;
@PostMapping
@PreAuthorize("hasRole('ROLE_MANAGER')")//it works
public ResponseEntity createInstructor(@Valid @RequestBody InstructorPostDto instructorPostDto) {
InstructorResponseDto createdInstructor = instructorService.createInstructor(instructorPostDto);
return new ResponseEntity<>(createdInstructor, HttpStatus.CREATED);
}
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.7'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.hh99'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
// security 관련 의존성
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// jwt 관련 의존성
implementation 'com.auth0:java-jwt:4.2.1'
}
tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder-jammy-base:latest'
}
tasks.named('test') {
useJUnitPlatform()
}
的数据
嗨,我正试图在我的小应用程序上应用Spring Security+JWT,我希望只有'BERGER'可以访问/lectures,/instructions,但即使用户有BERGER授权,他们也无法访问它们,所以我将hasAnyRole(“BERGER”)更改为BERGER All()并在Controller上应用@PreAuthorized,然后它可能会工作过滤器的顺序或只是代码问题。
1条答案
按热度按时间nhaq1z211#
有两种方法可以解决这个问题
1.您可以使用hasAuthority而不是hasRole
第一个月
1.权限应该在role前面加上“ROLE_"。您可以修改实体类中的getAuthorities()方法,扩展org.springframework.security.core.userdetails.UserDetails类,如下所示
字符串
difference-between-role-and-grantedauthority-in-spring-security这里是详细解释这个概念的链接。