是的,我知道这个问题已经问过了。但是关于这个问题,我也有一个不同的问题。 SecurityServiceImpl类中AuthenticationManager的authenticationManager对象,该对象未验证导致我在此时停留的细节。
我试图在每个步骤之后给出消息,通过它们可以跟踪特定代码是否起作用,并且在SecurityServiceImpl类中发现在此代码之后它不起作用
authenticationManager.authenticate(usernamePasswordAuthenticationToken);
我不知道这仅仅是我的理解。帮助我解决这个问题,如果您有更好的代码段可以解决此特定问题,请提供我的帮助。
安全配置
package com.demo.practice.configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);
@Autowired
private UserDetailsService userDetailsService;
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/register","/login").permitAll()
.antMatchers("/student/**").hasAuthority("STUDENT")
.antMatchers("/admin/**").hasAuthority("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login")
.defaultSuccessUrl("/dashboard");
http.csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
UserServiceImpl
package com.demo.practice.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.demo.practice.model.Credentials;
import com.demo.practice.model.Role;
import com.demo.practice.model.User;
import com.demo.practice.repository.UserRepository;
@Service
public class UserServiceImpl implements UserServiceInterface {
@Autowired
private BCryptPasswordEncoder encoder;
@Autowired
UserRepository userRepo;
@Override
public void saveUser(User user,Credentials credential) {
user.setCredential(credential);
user.getCredential().setUsername(user.getEmail());
user.getCredential().setRoles(Role.STUDENT);
user.getCredential().setPassword(encoder.encode(user.getCredential().getPassword()));
userRepo.save(user);
}
@Override
public User findUserByEmail(String name) {
User user=userRepo.findUserByEmail(name);
return user;
}
}
UserDetailsServiceImpl
package com.demo.practice.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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 org.springframework.transaction.annotation.Transactional;
import com.demo.practice.model.Credentials;
import com.demo.practice.repository.CredentialRepository;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
CredentialRepository credRepo;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Credentials credential =credRepo.findByUsername(username);
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
grantedAuthorities.add(new SimpleGrantedAuthority(credential.getRoles().toString()));
return new org.springframework.security.core.userdetails.User(credential.getUsername(), credential.getPassword(), grantedAuthorities);
}
}
SecurityServiceImpl
package com.demo.practice.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
@Service
public class SecurityServiceImpl implements SecurityServiceInterface {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(SecurityServiceImpl.class);
@Override
public String findLoggedInUsername() {
Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
if (userDetails instanceof UserDetails) {
return ((UserDetails)userDetails).getUsername();
}
return null;
}
@Override
public void autologin(String username, String password) {
System.out.println("in autologin "+username);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
System.out.println("in autologin at userdetails"+userDetails);
logger.info("after userdetails "+userDetails);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(),userDetails.getAuthorities());
logger.info("in autologin after usernamepasswordauthentication! ", usernamePasswordAuthenticationToken);
authenticationManager.authenticate(usernamePasswordAuthenticationToken);
logger.info("after authentication manager ", usernamePasswordAuthenticationToken);
if (usernamePasswordAuthenticationToken.isAuthenticated()) {
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
logger.debug(String.format("Auto login %s successfully!", username));
}
else System.out.println("auto login failed");
}
}
答案 0 :(得分:0)
您缺少一件事,如果要基于身份验证会话,则需要将WebAuthenticationDetails
添加到令牌中,例如:
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(principalUser, null, List.of(new SimpleGrantedAuthority(principalUser.getRole())));
token.setDetails(new WebAuthenticationDetails(request));
SecurityContextHolder.getContext().setAuthentication(token);
文档中的WebAuthenticationDetails
:
Records the remote address and will also set the session Id if a session already exists (it won't create one).
有关登录/注销过程的更多信息,请查看: https://github.com/pezetem/spring-security-angular-skeleton/blob/master/src/main/java/com/pezetem/blog/code/spring_security_custom_authorizers/security/SecurityController.java
更新:
好的,可能还有另一个原因对您不起作用。 Spring Security将默认前缀添加到角色。它等于ROLE_
。这意味着,当您为.hasAuthority("STUDENT")
配置的终结点角色必须等于ROLE_STUDENT
时,请看一下创建用户的行,并为Role.STUDENT
和角色分配角色值应为ROLE_STUDENT
而不是STUDENT