[英]Spring Security - Implementing UserDetailsService
I understand that Spring will pass the principal into controller's method if I include it as a method parameter. 我知道,如果将主体作为方法参数包含在内,Spring会将主体传递给控制器的方法。
I'm trying to extend this functionality by implementing UserDetailsService
: 我正在尝试通过实现
UserDetailsService
来扩展此功能:
I created a class named CustomUserDetails
that extends org.springframework.security.core.userdetails.User
我创建了一个名为
CustomUserDetails
的类,该类扩展了org.springframework.security.core.userdetails.User
I created a service named CustomUserDetailsService
that implements UserDetailsService
我创建了一个名为
CustomUserDetailsService
的服务,该服务实现了UserDetailsService
Exception 例外
HTTP Status 500 - Request processing failed;
HTTP状态500-请求处理失败; nested exception is java.lang.ClassCastException: org.springframework.security.authentication.UsernamePasswordAuthenticationToken cannot be cast to com.demo.model.CustomUserDetails
嵌套异常是java.lang.ClassCastException:org.springframework.security.authentication.UsernamePasswordAuthenticationToken无法转换为com.demo.model.CustomUserDetails
The following line in my controller method is throwing the exception: 我的控制器方法中的以下行引发异常:
CustomUserDetails userDetails = (CustomUserDetails) principal;
Controller.java Controller.java
@RequestMapping(value = "/dashboard", method = RequestMethod.GET)
public ModelAndView displayHomePage(ModelAndView modelAndView, Principal principal, HttpServletRequest request) {
// Throws exception here
CustomUserDetails userDetails = (CustomUserDetails) principal;
System.out.println(userDetails.getFirstName());
// Tried this and it also throws exception
// User cannot be cast to CustomUserDetails
//Authentication auth = SecurityContextHolder.getContext().getAuthentication();
//CustomUserDetails userDetails = (CustomUserDetails)auth.getPrincipal();
// Render template located at
// src/main/resources/templates/dashboard.html
modelAndView.setViewName("dashboard");
return modelAndView;
}
SecurityConfiguration.java SecurityConfiguration.java
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private DataSource dataSource;
@Value("${spring.queries.users-query}")
private String usersQuery;
@Value("${spring.queries.roles-query}")
private String rolesQuery;
@Autowired
SecurityHandler successHandler;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource).passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/register*").permitAll()
.antMatchers("/reset").permitAll().antMatchers("/forgot").permitAll().antMatchers("/grid").permitAll()
.antMatchers("/login").permitAll().antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().formLogin().loginPage("/login").failureUrl("/login?error")
.defaultSuccessUrl("/dashboard").successHandler(successHandler).usernameParameter("email")
.passwordParameter("password").and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout").and().exceptionHandling().accessDeniedPage("/access-denied");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/error**", "/resources/**", "/static/**", "/css/**", "/js/**", "/img/**");
}
}
CustomUserDetails.java CustomUserDetails.java
public class CustomUserDetails extends org.springframework.security.core.userdetails.User {
public CustomUserDetails(String username, String password,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
CustomUserDetailsService.java CustomUserDetailsService.java
@Service
public class CustomUserDetailsService implements UserDetailsService{
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException{
if(StringUtils.isEmpty(userName))
throw new UsernameNotFoundException("User name is empty");
//if you don't use authority based security, just add empty set
Set<GrantedAuthority> authorities = new HashSet<>();
CustomUserDetails userDetails = new CustomUserDetails(userName, "", authorities);
userDetails.setFirstName("Testing: " + new Date());
return userDetails;
}
}
in WebSecurityConfigurerAdapter
, you need add your register custom detail service: 在
WebSecurityConfigurerAdapter
,您需要添加注册自定义详细信息服务:
auth.userDetailsService(customDetailService)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource).passwordEncoder(bCryptPasswordEncoder);
}
Change your controller to: 将您的控制器更改为:
CONTROLLER CONTROLLER
@RequestMapping(value = "/dashboard", method = RequestMethod.GET)
public ModelAndView displayHomePage(ModelAndView modelAndView, Authentication authentication, HttpServletRequest request) {
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal;
Note it returns a Authentication object. 注意,它返回一个Authentication对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.