CREATE TABLE `t_role_permission` (
`role_id` varchar(32) NOT NULL,
`permission_id` varchar(32) NOT NULL,
PRIMARY KEY (`role_id`,`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
insert into `t_role_permission`(`role_id`,`permission_id`) values ('1','1'),('1','2');
修改UserDetailService
package com.itheima.security.springboot.dao;
import com.itheima.security.springboot.model.PermissionDto;
import com.itheima.security.springboot.model.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
/**
* @author Administrator
* @version 1.0
**/
@Repository
public class UserDao {
@Autowired
JdbcTemplate jdbcTemplate;
//根据账号查询用户信息
public UserDto getUserByUsername(String username){
String sql = "select id,username,password,fullname,mobile from t_user where username = ?";
//连接数据库查询用户
List<UserDto> list = jdbcTemplate.query(sql, new Object[]{username}, new BeanPropertyRowMapper<>(UserDto.class));
if(list !=null && list.size()==1){
return list.get(0);
}
return null;
}
//根据用户id查询用户权限
public List<String> findPermissionsByUserId(String userId){
String sql = "SELECT * FROM t_permission WHERE id IN(\n" +
"\n" +
"SELECT permission_id FROM t_role_permission WHERE role_id IN(\n" +
" SELECT role_id FROM t_user_role WHERE user_id = ? \n" +
")\n" +
")\n";
List<PermissionDto> list = jdbcTemplate.query(sql, new Object[]{userId}, new BeanPropertyRowMapper<>(PermissionDto.class));
List<String> permissions = new ArrayList<>();
list.forEach(c -> permissions.add(c.getCode()));
return permissions;
}
}
修改UserDetailService
package com.itheima.security.springboot.service;
import com.itheima.security.springboot.dao.UserDao;
import com.itheima.security.springboot.model.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
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 java.util.List;
/**
* @author Administrator
* @version 1.0
**/
@Service
public class SpringDataUserDetailsService implements UserDetailsService {
@Autowired
UserDao userDao;
//根据 账号查询用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//将来连接数据库根据账号查询用户信息
UserDto userDto = userDao.getUserByUsername(username);
if(userDto == null){
//如果用户查不到,返回null,由provider来抛出异常
return null;
}
//根据用户的id查询用户的权限
List<String> permissions = userDao.findPermissionsByUserId(userDto.getId());
//将permissions转成数组
String[] permissionArray = new String[permissions.size()];
permissions.toArray(permissionArray);
UserDetails userDetails = User.withUsername(userDto.getUsername()).password(userDto.getPassword()).authorities(permissionArray).build();
return userDetails;
}
}
Web授权
在上面例子中我们完成了认证拦截,并对
/r/**
下的某些资源进行简单的授权保护,但是我们想进行灵活的授权控
制该怎么做呢?通过给
http.authorizeRequests()
添加多个子节点来定制需求到我们的
URL
,如下代码:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() (1)
.antMatchers("/r/r1").hasAuthority("p1") (2)
.antMatchers("/r/r2").hasAuthority("p2") (3)
.antMatchers("/r/r3").access("hasAuthority('p1') and hasAuthority('p2')") (4)
.antMatchers("/r/**").authenticated() (5)
.anyRequest().permitAll() (6)
.and()
.formLogin()
// ...
}
(
1
)
http.authorizeRequests()
方法有多个子节点,每个
macher
按照他们的声明顺序执行。
(
2
)指定
"/r/r1"URL
,拥有
p1
权限能够访问
(
3
)指定
"/r/r2"URL
,拥有
p2
权限能够访问
(
4
)指定了
"/r/r3"URL
,同时拥有
p1
和
p2
权限才能够访问
(
5
)指定了除了
r1
、
r2
、
r3
之外
"/r/**"
资源,同时通过身份认证就能够访问,这里使用
SpEL
(
Spring Expression Language)表达式。。
(
6
)剩余的尚未匹配的资源,不做保护。