我正在使用Spring Web,Spring Security开发SpringBoot 2.0应用程序,并使用JWT进行身份验证。只有1个URI路径是公共的,任何人都可以访问,除了所有其他URI被保护并在任何尝试期间抛出“访问被拒绝”之外。我可以访问此公共URI,并使用用户名和密码在数据库中创建一个新用户。但是,当我尝试使用相同的凭据登录时,出现HTTP 403 Forbidden错误。
请在这里帮助我。谢谢
身份验证类别:-
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
logger.info("Entering attemptAuthentication@JWTAuthenticationFilter");
try{
ApplicationUser credential = new ObjectMapper()
.readValue(request.getInputStream(), ApplicationUser.class);
logger.info("Validating Credential:: {}, {}", credential.getUsername(), credential.getPassword());
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(credential.getUsername(),
credential.getPassword(), new ArrayList<>()));
}catch(IOException io){
throw new RuntimeException(io);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain, Authentication authResult)
throws IOException, ServletException {
logger.info("Entering successfulAuthentication@JWTAuthenticationFilter");
String jwtToken = Jwts.builder()
.setSubject(((User) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + SecurityConstant.EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SecurityConstant.SECRET)
.compact();
logger.info("JWT Token:: {}", jwtToken);
response.addHeader(SecurityConstant.HEADER_STRING, SecurityConstant.TOKEN_PREFIX + jwtToken);
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
logger.info("Failed authentication while attempting to access");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed");
}
}
授权等级:-
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
private static Logger logger = LoggerFactory.getLogger(JWTAuthorizationFilter.class);
public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
/**
*
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
logger.info("Entering doFilterInternal@JWTAuthorizationFilter");
String header = request.getHeader(SecurityConstant.HEADER_STRING);
logger.info("header:: {}", header);
if(null == header || !header.startsWith(SecurityConstant.TOKEN_PREFIX)){
logger.info("chaining");
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(header);
logger.info("Authentication:: {}", authentication);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
/**
*
* @param header
* @return
*/
private UsernamePasswordAuthenticationToken getAuthentication(String header){
logger.info("Entering getAuthenticationToken@JWTAuthorizationFilter");
logger.info("token::{}", header);
if(null != header){
//Parsing JWT Token
String user = Jwts.parser()
.setSigningKey(SecurityConstant.SECRET)
.parseClaimsJws(header.replace(SecurityConstant.TOKEN_PREFIX, ""))
.getBody()
.getSubject();
logger.info("user:: {}",user);
if(null != user){
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
WebSecurity类:-
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurity(UserDetailsService userDetailsService,
BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf()
.disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, SecurityConstant.SIGN_UP_URL).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
Application.properties文件:-
#spring.security.user.name=user
#spring.security.user.password=user
spring.data.mongodb.uri=mongodb://localhost:27017/myspringdb
用于注册的PostMan测试数据(正在运行):-
http://localhost:8080/users/sign-up
{
"id":"2",
"username":"user",
"password":"user",
"emailAddress":"abc@sample.com"
}
用于登录的PostMan测试数据(不起作用):-
标题:content-type:application / json
{
"username":"user",
"password":"user"
}
并且还想知道Im是否可以通过使用spring-security来解决问题,因为在运行程序时,程序会自行生成密码,如下所示:-
使用生成的安全密码:ki908a3f-00ec-98cc-bn02-823ead10f153
我应该使用保存在数据库(mongodb)中的我自己的凭据还是今年春天生成的用于身份验证的密码?
谢谢