我在 spring 安全性方面遇到问题,注册工作并使用加密密码添加管理员和客户端,但当我尝试使用"\login"登录时,它向我显示错误 404 未找到资源
2020-07-07 13:43:19.912 DEBUG 12156 --- [nio-9000-exec-9] o.s.web.servlet.DispatcherServlet : GET "/login", parameters={}
2020-07-07 13:43:20.490 DEBUG 12156 --- [nio-9000-exec-9] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
2020-07-07 13:43:21.178 DEBUG 12156 --- [nio-9000-exec-9] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
2020-07-07 13:43:21.178 DEBUG 12156 --- [nio-9000-exec-9] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND
2020-07-07 13:43:21.227 DEBUG 12156 --- [nio-9000-exec-9] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}
2020-07-07 13:43:21.253 DEBUG 12156 --- [nio-9000-exec-9] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2020-07-07 13:43:21.471 DEBUG 12156 --- [nio-9000-exec-9] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Using 'application/hal+json', given [*/*] and
supported [application/hal+json]
2020-07-07 13:43:21.477 DEBUG 12156 --- [nio-9000-exec-9] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Writing [{timestamp=Tue Jul 07 13:43:21 CEST 2020, status=404, error=Not Found, message=No message available, (truncated)...]
2020-07-07 13:43:21.679 DEBUG 12156 --- [nio-9000-exec-9] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404
安全配置.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/login").permitAll();
http.authorizeRequests().anyRequest().permitAll();
// http.authorizeRequests().anyRequest().authenticated();
http.addFilter(new JWTAuthenticationFilter(authenticationManager()));
http.addFilterBefore(new JWTAuthorizationFiler(), UsernamePasswordAuthenticationFilter.class);
}
JWTAuthorizationFiler
public class JWTAuthorizationFiler extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers,authorization");
response.addHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin, Access-Control-Allow-Credentials, authorization");
if(request.getMethod().equals("OPTIONS")){
response.setStatus(HttpServletResponse.SC_OK);
}
else if(request.getRequestURI().equals("/login")) {
filterChain.doFilter(request, response);
return;
}
else {
String jwtToken = request.getHeader(SecurityParams.JWT_HEADER_NAME);
System.out.println("Token="+jwtToken);
if (jwtToken == null || !jwtToken.startsWith(SecurityParams.HEADER_PREFIX)) {
filterChain.doFilter(request, response);
return;
}
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SecurityParams.SECRET)).build();
String jwt = jwtToken.substring(SecurityParams.HEADER_PREFIX.length());
DecodedJWT decodedJWT = verifier.verify(jwt);
System.out.println("JWT="+jwt);
String username = decodedJWT.getSubject();
List<String> roles = decodedJWT.getClaims().get("roles").asList(String.class);
System.out.println("username="+username);
System.out.println("roles="+roles);
Collection<GrantedAuthority> authorities = new ArrayList<>();
roles.forEach(rn -> {
authorities.add(new SimpleGrantedAuthority(rn));
});
UsernamePasswordAuthenticationToken Admin =
new UsernamePasswordAuthenticationToken(username, null,authorities);
SecurityContextHolder.getContext().setAuthentication(Admin);
filterChain.doFilter(request, response);
}
}
JWTAuthenticationFilter.java
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
Admin appUser= new ObjectMapper().readValue(request.getInputStream(),Admin.class);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(appUser.getUsername(),appUser.getPassword()));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public Authentication attemptAuthentication1(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
Admin appUser= new ObjectMapper().readValue(request.getInputStream(),Admin.class);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(appUser.getUsername(),appUser.getPassword()));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
User user=(User)authResult.getPrincipal();
List<String> roles=new ArrayList<>();
authResult.getAuthorities().forEach(a->{
roles.add(a.getAuthority());
});
String jwt= JWT.create()
.withIssuer(request.getRequestURI())
.withSubject(user.getUsername())
.withArrayClaim("roles",roles.toArray(new String[roles.size()]))
.withExpiresAt(new Date(System.currentTimeMillis()+SecurityParams.EXPIRATION))
.sign(Algorithm.HMAC256(SecurityParams.SECRET));
response.addHeader(SecurityParams.JWT_HEADER_NAME,jwt);
}
帐户服务.java
public class AccountServiceImpl implements AccountService{
private AppUserRepository appUserRepository;
private AppRoleRepository appRoleRepository;
private BCryptPasswordEncoder bCryptPasswordEncoder;
public AccountServiceImpl(AppUserRepository appUserRepository, AppRoleRepository appRoleRepository, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.appUserRepository = appUserRepository;
this.appRoleRepository = appRoleRepository;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
//othercode
@Override
public Utilisateur loadUserByUsername(String username) {
return appUserRepository.findByUsername(username);
}
@Override
public void addRoleToUser(String username, String rolename) {
Utilisateur appUser=appUserRepository.findByUsername(username);
AppRole appRole=appRoleRepository.findByRoleName(rolename);
appUser.getRoles().add(appRole);
}
管理员控制器.java
@GetMapping("/users")
public Utilisateur getuser(Principal principal){
return appUserRepository.findByUsername(principal.getName());
}
检查端点"\login"的路径,一般是"/login",验证你用来登录的端点网址,例如:"http://localhost:8080/your_endpoint_path"。 由于您制作了用户名密码身份验证过滤器的自定义版本,因此您需要指定用于登录的路径,尝试将其添加到您的 SecurityConfig.java 类
中@Override
protected void configure(HttpSecurity http) throws Exception {
JWTAuthenticationFilter.setFilterProcessesUrl("/your_endpoint_path");
// the rest of your configuration code
}
' 因此,您可以通过指定"/your_endpoint_path"进行身份验证,希望这会有所帮助。
由于 evrything 是在多个过滤器中完成的,因此您只需要一个"/login"端点即可返回
@PostMapping("/login")
public ResponseEntity<String> authenticate(HttpServletResponse response) {
String jwt = response.getHeader(SecurityParams.JWT_HEADER_NAME);
return new ResponseEntity<>(jwt, HttpStatus.OK);
}