此项目config层编写密码编码器,domain层是两个实体,接口层两个验证方法,服务层进行用户验证,问题出在对Authority接口的方法上,运行项目时,无法找到Authority的类型,以下是几个错误原因:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userDetailServiceImpl': Unsatisfied dependency expressed through field 'customerService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerService': Unsatisfied dependency expressed through field 'authorityRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authorityRepository' defined in com.itheima.repository.AuthorityRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.itheima.repository.AuthorityRepository.findAuthoritiesByUsername(java.lang.String)! No property username found for type Authority!
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerService': Unsatisfied dependency expressed through field 'authorityRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authorityRepository' defined in com.itheima.repository.AuthorityRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.itheima.repository.AuthorityRepository.findAuthoritiesByUsername(java.lang.String)! No property username found for type Authority!
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authorityRepository' defined in com.itheima.repository.AuthorityRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.itheima.repository.AuthorityRepository.findAuthoritiesByUsername(java.lang.String)! No property username found for type Authority!
Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List com.itheima.repository.AuthorityRepository.findAuthoritiesByUsername(java.lang.String)! No property username found for type Authority!
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property username found for type Authority!
package com.itheima.service;
import com.itheima.domain.Authority;
import com.itheima.domain.Customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.*;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
//自定义一个UserDetailsService接口实现类进行用户认证信息封装
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private CustomerService customerService;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//通过业务方法获取用户及权限信息
Customer customer = customerService.getCustomer(s);
List<Authority> authorities = customerService.getCustomerAuthority(s);
//对用户权限进行封装
List<SimpleGrantedAuthority> list = authorities.stream()
.map(authority -> new SimpleGrantedAuthority(authority.getAuthority()))
.collect(Collectors.toList());
//返回封装的UserDetails用户详情类
if (customer != null){
UserDetails userDetails = new User(customer.getUsername(), customer.getPassword(), list);
return userDetails;
}else {
//如果查询的用户不存在(用户名不存在),必须抛出异常
throw new UsernameNotFoundException("当前用户不存在!");
}
}
}
package com.itheima.service;
import com.itheima.domain.Authority;
import com.itheima.domain.Customer;
import com.itheima.repository.AuthorityRepository;
import com.itheima.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
//对用户数据结合Redis缓存进行业务处理
@Service
public class CustomerService {
@Autowired
private CustomerRepository customerRepository;
@Autowired
private AuthorityRepository authorityRepository;
@Autowired
private RedisTemplate redisTemplate;
//业务控制:使用唯一用户名查询用户信息
public Customer getCustomer(String username){
Customer customer = null;
Object o = redisTemplate.opsForValue().get("customer_" + username);
if (o != null){
customer = (Customer) o;
}else {
customer = customerRepository.findByUsername(username);
if (customer != null){
redisTemplate.opsForValue().set("customer_" + username,customer);
}
}
return customer;
}
//业务控制:使用唯一用户名查询用户权限
public List<Authority> getCustomerAuthority(String username){
List<Authority> authorities = null;
Object o = redisTemplate.opsForValue().get("authorities_" + username);
if (o != null){
authorities = (List<Authority>) o;
}else {
authorities=authorityRepository.findAuthoritiesByUsername(username);
if (authorities.size() > 0){
redisTemplate.opsForValue().set("authorities_" + username,authorities);
}
}
return authorities;
}
}
package com.itheima.repository;
import com.itheima.domain.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CustomerRepository extends JpaRepository<Customer,Integer> {
Customer findByUsername(String username);
}
package com.itheima.repository;
import com.itheima.domain.Authority;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface AuthorityRepository extends JpaRepository<Authority,String> {
List<Authority> findAuthoritiesByUsername(String username);
}
package com.itheima.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;
@Entity(name = "t_customer")
public class Customer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
package com.itheima.domain;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;
@Entity(name = "t_authority")
public class Authority implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String authority;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
@Override
public String toString() {
return "Authority{" +
"id=" + id +
", authority='" + authority + '\'' +
'}';
}
}
package com.itheima.config;
import com.itheima.service.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer;
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;
import javax.sql.DataSource;
@EnableWebSecurity //开启MVC Security安全支持
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Qualifier("dataSource")
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailServiceImpl userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//设置密码编码器
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
//内存身份认证:模拟了测试用户
/*InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> authenticationManagerBuilderInMemoryUserDetailsManagerConfigurer = auth.inMemoryAuthentication().passwordEncoder(bCryptPasswordEncoder);
authenticationManagerBuilderInMemoryUserDetailsManagerConfigurer.withUser("shitou").password(bCryptPasswordEncoder.encode("123")).roles("common");
authenticationManagerBuilderInMemoryUserDetailsManagerConfigurer.withUser("lisi").password(bCryptPasswordEncoder.encode("321")).roles("vip");
*/
//使用jdbc进行身份认证
/*JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> authenticationManagerBuilderJdbcUserDetailsManagerConfigurer = auth.jdbcAuthentication().passwordEncoder(bCryptPasswordEncoder);
authenticationManagerBuilderJdbcUserDetailsManagerConfigurer.dataSource(dataSource);
authenticationManagerBuilderJdbcUserDetailsManagerConfigurer.usersByUsernameQuery("SELECT username,PASSWORD,valid FROM t_customer WHERE username = ?");
authenticationManagerBuilderJdbcUserDetailsManagerConfigurer.authoritiesByUsernameQuery("SELECT c.username,a.authority FROM t_customer c,t_authority a,t_customer_authority ta WHERE c.id = ta.customer_id AND a.id = ta.authority_id AND c.username = ?");
*/
//使用UserDetailsService进行认证
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("details/common/**").hasRole("common")
.antMatchers("details/vip/**").hasRole("vip")
.anyRequest().authenticated()
.and().formLogin();
}
}