我不知道如何能够做从端点localhost请求:8080/管理/**
首先,我在我的端点localhost:8080/API/auth/register上进行所有操作,并使用此JSON输入我已经具有“ADMIN”角色的用户:
{
"username": "Admin",
"password": "password"
}
下面是UserModel类
@Getter
@Setter
@Document(collection = "users")
public class UserModel {
@Id
private ObjectId id;
private String username;
private String password;
@DocumentReference
private List<Role> roles = new ArrayList<>();
}
这是我的角色类
@Getter
@Setter
@Document(collection = "roles")
public class Role {
@Id
private ObjectId id;
private String name;
}
然后,我尝试使用此JSON在端点localhost:8080/manage/addProduct添加我的产品
{
"name": "monitor",
"category": "electronic",
"price": 1799.99,
"imageUrl": "URL"
}
但我没有被授权。我做错了什么?
ProductController
@RestController
@RequestMapping("/manage")
public class ProductController {
@Autowired
private ProductService productService;
@PostMapping("/addProduct")
public Product saveProduct(@RequestBody Product product){
return productService.saveProduct(product);
}
@DeleteMapping("/removeProduct/{id}")
public ResponseEntity<?> removeProduct(@PathVariable ObjectId id){
return productService.deleteProduct(id);
}
@PutMapping("/updateProduct/{id}")
public Product updateProduct(@PathVariable ObjectId id, @RequestBody Product product) throws ServiceNotFoundException {
return productService.updateProduct(id, product);
}
}
AuthController
@RestController
@RequestMapping("/api/auth")
public class AuthController {
private AuthenticationManager authenticationManager;
private UserRepository userRepository;
private RoleRepository roleRepository;
private PasswordEncoder passwordEncoder;
private JWTGenerator jwtGenerator;
@Autowired
private HttpServletResponse httpServletResponse;
@Autowired
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository,
RoleRepository roleRepository, PasswordEncoder passwordEncoder, JWTGenerator jwtGenerator) {
this.authenticationManager = authenticationManager;
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.passwordEncoder = passwordEncoder;
this.jwtGenerator = jwtGenerator;
}
@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody AuthDto registerDto) {
if(userRepository.existsByUsername(registerDto.getUsername())) {
return ResponseEntity.badRequest().body("Username is taken");
}
UserModel user = new UserModel();
user.setUsername(registerDto.getUsername());
user.setPassword(passwordEncoder.encode(registerDto.getPassword()));
Role roles = roleRepository.findByName("USER").orElse(null);
user.setRoles(Collections.singletonList(roles));
userRepository.save(user);
ResponseEntity<AuthResponseDTO> tokenResponse = login(registerDto, httpServletResponse);
if (tokenResponse != null && tokenResponse.getBody() != null) {
String token = tokenResponse.getBody().getAccessToken();
return ResponseEntity.ok(new AuthResponseDTO(token));
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred");
}
}
@PostMapping("/login")
public ResponseEntity<AuthResponseDTO> login(@RequestBody AuthDto loginDto, HttpServletResponse response){
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginDto.getUsername(),
loginDto.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String token = jwtGenerator.generateToken(authentication);
Cookie cookie = new Cookie("jwtToken", token);
cookie.setPath("/");
cookie.setMaxAge(7200);
cookie.setHttpOnly(true);
cookie.setSecure(true);
response.addCookie(cookie);
return new ResponseEntity<>(new AuthResponseDTO(token), HttpStatus.OK);
}
@PostMapping("/logout")
public ResponseEntity<String> logout(HttpServletResponse response){
SecurityContextHolder.clearContext();
Cookie cookie = new Cookie("jwtToken", null);
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
return ResponseEntity.ok("Logged out successfully");
}
}
CustomUserDetailService
@Service
public class CustomUserDetailsService implements UserDetailsService {
private UserRepository userRepository;
@Autowired
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserModel user = userRepository.findByUsername(username).orElseThrow(()
-> new UsernameNotFoundException("Username not found Exception"));
return new User(user.getUsername(), user.getPassword(), mapRolesToAuthorities(user.getRoles()));
}
private Collection<GrantedAuthority> mapRolesToAuthorities(List<Role> roles) {
return roles.stream().map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
}
JWTAuthenticationFilter
public class JWTAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JWTGenerator tokenGenerator;
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String token = getJWTFromRequest(request);
if(StringUtils.hasText(token) && tokenGenerator.validateToken(token)) {
String username = tokenGenerator.getUsernameFromJWT(token);
UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()
);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
filterChain.doFilter(request, response);
}
private String getJWTFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if(StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
JwtAuthEntryPoint酒店
@Component
public class JwtAuthEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response
.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
}
}
JWTGenerator
@Component
public class JWTGenerator {
private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS512);
public String generateToken(Authentication authentication) {
String username = authentication.getName();
Date currentDate = new Date();
Date expireDate = new Date(currentDate.getTime() + SecurityConstants.JWT_EXPIRATION);
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(expireDate)
.signWith(key, SignatureAlgorithm.HS512)
.compact();
}
public String getUsernameFromJWT(String token) {
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody().getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token);
return true;
} catch (Exception ex) {
throw new AuthenticationCredentialsNotFoundException(
"JWT was expired or incorrect", ex.fillInStackTrace()
);
}
}
}
SecurityConfig
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtAuthEntryPoint jwtAuthEntryPoint;
@Autowired
CustomUserDetailsService customUserDetailsService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.
csrf(AbstractHttpConfigurer::disable)
.exceptionHandling(
(exception)-> exception
.authenticationEntryPoint(jwtAuthEntryPoint)
)
.sessionManagement((session) ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests((auth) ->
auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/manage/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults());
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean public JWTAuthenticationFilter jwtAuthenticationFilter() {
return new JWTAuthenticationFilter();
}
}
1条答案
按热度按时间zpqajqem1#
您为Cookie定义的设置之一是
secure
标志:cookie.setSecure(true);
。安全标志允许cookie仅与https
一起发送-参见here。由于您在本地主机上使用http
,因此不会发送cookie,因此没有授权。把这行注解掉。