Spring、@RolesAllowed 和数据库以保护页面
Spring, @RolesAllowed and database to secure pages
我的数据库中有两个表格。用户和 user_role.
CREATE TABLE `user` (
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`enable` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`username`),
UNIQUE KEY `unique_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `user_roles` (
`user_role_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`ROLE` varchar(45) NOT NULL,
PRIMARY KEY (`user_role_id`),
UNIQUE KEY `uni_username_role` (`ROLE`,`username`),
KEY `fk_username_idx` (`username`),
CONSTRAINT `fk_username` FOREIGN KEY (`username`) REFERENCES `user` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
'ROLE' in user_roles 显示用户拥有的角色{ROLE_USER, ROLE_ADMIN}
我想使用@RolesAllowed 来拒绝用户访问某些页面(并授予管理员访问权限),但我不知道如何从数据库中获取 user_role 并发送它到 RolesAllowed。
在 Controller 中获取 user_role 不是问题,但我认为检查每个功能中的用户角色不是个好主意。
或者,也许有比使用@RolesAllowed 更好的解决方案?
抱歉这个愚蠢的问题,我第一次看到 Spring 已经 5 个小时了。
您没有详细说明您正在构建的应用程序的体系结构,但作为初学者,我可以为您提供一些我目前正在构建的应用程序的示例。我正在使用 Spring Boot、JPA、Spring Data 和 Spring Security。我有一个类似的需求,然后这样解决了:
我已经实现了 UserDetailsService 接口。它用于检索有关尝试登录的用户的信息。当我使用 JPA 和 Spring 数据时,服务和模型 类 看起来像这样(getters、setters 和大多数字段已删除简洁):
@Entity
// in your case this would map to the User table
public class Profile implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// you should probably use bean validation / jpa to assure uniqueness etc.
private String name;
...
@ElementCollection(fetch = FetchType.EAGER)
private Set<Role> roles = ImmutableSet.<Role> of(new Role("USER"));
...
}
@Embeddable
// in your case this would map to the user_role table
public class Role implements GrantedAuthority {
public final static Role USER = new Role("USER");
public final static Role ADMIN = new Role("ADMIN");
private String authority;
...
}
@Transactional
@Service
public class ProfileService implements UserDetailsService {
private final ProfileRepository profileRepository;
@Autowired
public ProfileService(ProfileRepository profileRepository){
this.profileRepository = profileRepository;
}
public Profile loadUserByUsername(String username) throws UsernameNotFoundException {
Profile profile = profileRepository.findByUsername(username);
// this is the only way to authenticate
if (profile == null) {
throw new UsernameNotFoundException("security.userNotFound");
}
return profile;
}
// you may want to add profile creation etc.
...
}
完成此设置后,我必须配置 Spring 安全性才能使用此服务。我主要使用 Java 配置,所以配置看起来像。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ProfileService profileService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(profileService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login")
.permitAll()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/**")
.authenticated()
...
// you may want to put more config here
}
}
我的数据库中有两个表格。用户和 user_role.
CREATE TABLE `user` (
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`enable` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`username`),
UNIQUE KEY `unique_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `user_roles` (
`user_role_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(45) NOT NULL,
`ROLE` varchar(45) NOT NULL,
PRIMARY KEY (`user_role_id`),
UNIQUE KEY `uni_username_role` (`ROLE`,`username`),
KEY `fk_username_idx` (`username`),
CONSTRAINT `fk_username` FOREIGN KEY (`username`) REFERENCES `user` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
'ROLE' in user_roles 显示用户拥有的角色{ROLE_USER, ROLE_ADMIN}
我想使用@RolesAllowed 来拒绝用户访问某些页面(并授予管理员访问权限),但我不知道如何从数据库中获取 user_role 并发送它到 RolesAllowed。
在 Controller 中获取 user_role 不是问题,但我认为检查每个功能中的用户角色不是个好主意。
或者,也许有比使用@RolesAllowed 更好的解决方案?
抱歉这个愚蠢的问题,我第一次看到 Spring 已经 5 个小时了。
您没有详细说明您正在构建的应用程序的体系结构,但作为初学者,我可以为您提供一些我目前正在构建的应用程序的示例。我正在使用 Spring Boot、JPA、Spring Data 和 Spring Security。我有一个类似的需求,然后这样解决了:
我已经实现了 UserDetailsService 接口。它用于检索有关尝试登录的用户的信息。当我使用 JPA 和 Spring 数据时,服务和模型 类 看起来像这样(getters、setters 和大多数字段已删除简洁):
@Entity
// in your case this would map to the User table
public class Profile implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// you should probably use bean validation / jpa to assure uniqueness etc.
private String name;
...
@ElementCollection(fetch = FetchType.EAGER)
private Set<Role> roles = ImmutableSet.<Role> of(new Role("USER"));
...
}
@Embeddable
// in your case this would map to the user_role table
public class Role implements GrantedAuthority {
public final static Role USER = new Role("USER");
public final static Role ADMIN = new Role("ADMIN");
private String authority;
...
}
@Transactional
@Service
public class ProfileService implements UserDetailsService {
private final ProfileRepository profileRepository;
@Autowired
public ProfileService(ProfileRepository profileRepository){
this.profileRepository = profileRepository;
}
public Profile loadUserByUsername(String username) throws UsernameNotFoundException {
Profile profile = profileRepository.findByUsername(username);
// this is the only way to authenticate
if (profile == null) {
throw new UsernameNotFoundException("security.userNotFound");
}
return profile;
}
// you may want to add profile creation etc.
...
}
完成此设置后,我必须配置 Spring 安全性才能使用此服务。我主要使用 Java 配置,所以配置看起来像。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ProfileService profileService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(profileService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login")
.permitAll()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/**")
.authenticated()
...
// you may want to put more config here
}
}