【发布时间】:2022-02-17 19:37:41
【问题描述】:
我正在尝试在 Spring Boot 应用程序上配置 Spring Security,结果 Postman 给出 401 Unauthorized ,请谁能帮我解决这个错误
控制器
package com.example.demo.controller;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
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;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
@CrossOrigin(origins = "http://localhost:8080")
@RestController
@RequestMapping("/api")
public class UserController {
@Autowired
private UserService userService;
@PostConstruct
public void initRoleAndUser() {
userService.initRoleAndUser();
}
@PostMapping({"/registerNewUser"})
public User registerNewUser(@RequestBody User user) {
return userService.registerNewUser(user);
}
@GetMapping({"/forAdmin"})
@PreAuthorize("hasRole('Admin')")
public String forAdmin(){
return "This URL is only accessible to the admin";
}
@GetMapping({"/forUser"})
@PreAuthorize("hasRole('User')")
public String forUser(){
return "This URL is only accessible to the user";
}
}
配置
package configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
private UserDetailsService jwtService;
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors();
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/authenticate", "/registerNewUser").permitAll()
.antMatchers(HttpHeaders.ALLOW).permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
;
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(jwtService).passwordEncoder(passwordEncoder());
}
}
JwtService
package com.example.demo.service;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.example.demo.dao.UserDao;
import com.example.demo.Util.JwtUtil;
import com.example.demo.entity.User;
import com.example.demo.entity.JwtResponse;
import com.example.demo.entity.JwtRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.HashSet;
import java.util.Set;
@Service
public class JwtService implements UserDetailsService {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDao userDao;
private AuthenticationManager authenticationManager;
public JwtResponse createJwtToken(JwtRequest jwtRequest) throws Exception {
String userName = jwtRequest.getName();
String userPassword = jwtRequest.getUser_code();
authenticate(userName, userPassword);
UserDetails userDetails = loadUserByUsername(userName);
String newGeneratedToken = jwtUtil.generateToken(userDetails);
User user = userDao.findById(userName).get();
return new JwtResponse(user, newGeneratedToken);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDao.findById(username).get();
if (user != null) {
return new org.springframework.security.core.userdetails.User(
user.getName(),
user.getUser_code(),
getAuthority(user)
);
} else {
throw new UsernameNotFoundException("User not found with username: " + username);
}
}
private Set getAuthority(User user) {
Set<SimpleGrantedAuthority> authorities = new HashSet<>();
user.getRoles().forEach(role -> {
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
});
return authorities;
}
private void authenticate(String userName, String userPassword) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, userPassword));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED");
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS");
}
}
}
我使用邮递员进行测试,当我对“http://localhost:8080/forAdmin”执行 GET 操作时,我收到错误 401 Unauthorized
【问题讨论】:
-
为什么要发送
POST请求http://localhost:8080/forAdmin?您的控制器已被提及,它是一个GET请求。@GetMapping({"/forAdmin"}) -
是的,在邮递员中我把它 GET 并且我有同样的问题,谢谢你的回答
-
既然你有
@RequestMapping("/api"),那么端点就是http://localhost:8080/api/forAdmin
标签: java spring spring-security postman user-roles