【发布时间】:2021-10-14 15:42:27
【问题描述】:
我正在尝试从我的 MySecurityConfiguration 类中为 JWT 自动装配 AuthenticationManager 组件,因为它失败了。谁能建议我根本原因或如何解决这个问题。
MySecurtyConfiguration.java
package com.expensesd.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.expenses.demo.service.UserDetailServiceImplementation;
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfigurations extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAutenticationEntryyPoint unauthorizedHandler;
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private UserDetailServiceImplementation userDetailServiceImplementation;
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.userDetailServiceImplementation).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.cors().disable()
.authorizeRequests()
.antMatchers("/generate-token","/user/").permitAll()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
AuthenticateController
package com.expenses.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
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.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.expenses.demo.modal.JwtRequest;
import com.expenses.demo.modal.JwtResponse;
import com.expenses.demo.service.UserDetailServiceImplementation;
import com.expensesd.demo.config.JwtUtil;
@RestController
public class AuthenticateController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailServiceImplementation userDetailServiceImplementation;
@Autowired
private JwtUtil jwtUtils;
//generate token
@PostMapping("/generate-token")
public ResponseEntity<?> generateToken(@RequestBody JwtRequest jwtRequest) throws Exception{
try {
this.authenticate(jwtRequest.getUsername(),jwtRequest.getPassword());
} catch (UsernameNotFoundException e) {
e.printStackTrace();
System.out.println("User Not Found");
}
//Done Authenticate
UserDetails userDetails = this.userDetailServiceImplementation.loadUserByUsername(jwtRequest.getUsername());
String token = this.jwtUtils.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
private void authenticate(String username,String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("User Disable" +e.getMessage());
}catch (BadCredentialsException e) {
throw new Exception("Invalid Credentials" +e.getMessage());
}
}
}
UserDetailServiceImplementation.java
package com.expenses.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
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.expenses.demo.modal.User;
import com.expenses.demo.repository.UserRepository;
@Service
public class UserDetailServiceImplementation implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.userRepository.findByUsername(username);
if(user==null) {
System.out.println("User Not Found");
throw new UsernameNotFoundException("No User Found");
}
return user;
}
}
JwtUtil.java
package com.expensesd.demo.config;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
public class JwtUtil {
private String SECRET_KEY = "secret";
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
public Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
JwtAuthenticationEntryyPoint.java
package com.expensesd.demo.config;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
@Component
public class JwtAutenticationEntryyPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,"UnAuthorized : Server");
}
}
错误
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
[2m2021-08-11 12:43:21.452[0;39m [31mERROR[0;39m [35m14444[0;39m [2m---[0;39m [2m[ restartedMain][0;39m [36mo.s.b.d.LoggingFailureAnalysisReporter [0;39m [2m:[0;39m
***************************
APPLICATION FAILED TO START
***************************
Description:
Field authenticationManager in com.expenses.demo.controller.AuthenticateController required a bean of type 'org.springframework.security.authentication.AuthenticationManager' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.springframework.security.authentication.AuthenticationManager' in your configuration.
【问题讨论】:
-
在我的配置中,我不需要定义
authenticationManagerBean。相反,我只是让 spring 使用默认值 - 就像你似乎正在做的那样。我还在@EnableGlobalMethodSecurity中启用了jsr250。不确定这是否应该有所作为? ??????
标签: java spring spring-boot spring-mvc jwt