1、spring security 是进行权限认证的。
2、项目中都是使用基于数据库的认证方式。
首先我们创建权限相关的表。
一般的权限控制会有
user → role → data_privilege
user →data_privilege
用户通过role 进行控制,数据权限和role 绑定,好处在于可以批量控制用户的权限。
单个用户进行单个设置,这个比较灵活。
-- 用户表
CREATE TABLE t_user(
id int ,
username varchar(32),
password varchar(255),
enabled tinyint(1),
locked tinyint(1)
)
--- 角色表
create table t_role(
id int,
nameEN varchar(32),
nameZH varchar(50)
)
---用户角色表
create table t_user_role(
id int,
uid int,
rid int
)
---用户角色url
create table t_role_url(
id int,
rid int,
urlId int
)
---用户菜单表
create table t_menu(
id int,
url varchar(255),
desc varchar(50),
actived TINYINT(1)
)
---用户数据权限表
create table t_data_privileg(
id int ,
idType varchar(32),
authIds int,
privId int,
privType int,
isDel tinyint(1),
create_date TIMESTAMP,
expire_date TIMESTAMP
)
3、需要实现UserDetailService 的loadUserByUsername 方法
/**
*
*/
package com.security.service;
import org.springframework.beans.factory.annotation.Autowired;
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 com.security.dao.UserMapper;
import com.security.entity.User;
/**
* @author fandong
*
*/
@Service
public class UserService implements UserDetailsService{
@Autowired
public UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
System.out.println("start 调用 数据库继续查询。。。。。");
User user = userMapper.loadUserByUsername(username);
if(user == null) {
throw new UsernameNotFoundException("账户不存在");
}
user.setRoles(userMapper.getUserRolesByUid(user.getId()));
System.out.println(user.toString());
return user;
}
}
4、实现User UserDetail接口
/**
*
*/
package com.security.entity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
/**
* @author fandong
*
*/
public class User implements UserDetails{
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", enabled=" + enabled
+ ", locked=" + locked + ", roles=" + roles + "]";
}
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
private String username;
private String password;
private Boolean enabled;
private Boolean locked;
private List<Role> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
for(Role role: roles) {
authorities.add(new SimpleGrantedAuthority(role.getNameEN()));
}
System.out.println("-----------获取权限列表-------");
return authorities;
}
@Override
public String getPassword() {
// TODO Auto-generated method stub
return password;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return username;
}
@Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
// TODO Auto-generated method stub
return enabled;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
5、实现UserMapper 方法
/**
*
*/
package com.security.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.security.entity.Role;
import com.security.entity.User;
/**
* @author fandong
*
*/
public interface UserMapper {
@Select("select * from t_user where username=#{username}")
User loadUserByUsername(@Param("username") String username) throws UsernameNotFoundException;
@Select("select * from t_role r,t_user_role ur where r.id=ur.rid and ur.uid=#{id}")
List<Role> getUserRolesByUid(@Param("id") Integer id);
}
5、显现WebSecurityConfigurerAdapter
/**
*
*/
package com.security.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.security.service.UserService;
/**
* @author fandong
*
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder PasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Autowired
UserService userService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Auto-generated method stub
auth.userDetailsService(userService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// TODO Auto-generated method stub
System.out.println("开始执行。。。。。。。");
http.authorizeRequests().antMatchers("/admin/**").hasRole("admin")
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login").permitAll()
.and()
.csrf()
.disable();
//super.configure(http);
}
}
注意Role 进行匹配时,会自动添加ROLE_ 前缀。
6、测试Controller
package com.security.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/admin/hello")
public String admin() {
return "hello,admin!";
}
@RequestMapping("/hello")
public String hello() {
return "hello";
}
}
7、测试,数据库存储角色名称一定要加ROLE_ 前缀。