这个与我前面写的shiro案例用的是同一个案例 只是使用的中间件不一样 这个比shiro的整合更简单
shiro案例首先是创建一个springboot项目 导入坐标
<!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.16</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.0</version> </dependency> <!-- 以下是>spring security依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
前面一样的也是写基础代码 与 shiro中的相同 注意里面的@PreAuthorize 是声明权限的注解
UserController
@RestController
public class UserController {
@Autowired
private UserService userService;
//个人主页
@RequestMapping("/home")
@PreAuthorize("hasAuthority('user-home')") //权限注解
public String home() {
return "访问个人主页成功";
}
//添加
@RequestMapping(value = "/user", method = RequestMethod.POST)
@PreAuthorize("hasAuthority('user-add')")
public String add() {
return "添加用户成功";
}
//查询
@GetMapping("/user")
@PreAuthorize("hasAuthority('user-find')")
public User find(String id) {
return userService.findAllById(id);
}
//更新
@RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
@PreAuthorize("hasAuthority('user-update')")
public String update(@PathVariable String id) {
return "更新用户成功";
}
//删除
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
@PreAuthorize("hasAuthority('user-delete')")
public String delete(@PathVariable String id) {
return "删除用户成功";
}
//登陆成功
@RequestMapping(value = "/login-success")
public String loginSuccess() {
return "登陆成功!";
}
//未登陆与未授权页面
@RequestMapping(value = "/autherror")
public String autherror() {
return "未登录";
}
}
UserService
@Service
public class UserService {
@Autowired
private UserDao userDao;
public User findByName(String name) {
return userDao.findUserByName(name);
}
public User findAllById(String id){
return userDao.findUserById(id);
}
}
SpringDataUserDetailsService
@Service
public class SpringDataUserDetailService implements UserDetailsService {
@Autowired
UserService userService;
//根据账号查询用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findByName(username);
if (username==null){
return null;
}
User userDetail = userService.findAllById(user.getId());
Set<String> roles = new HashSet<>();//所有角色
Set<String> perms = new HashSet<>();//所有权限
for (Role role : userDetail.getRoles()) {
roles.add(role.getName());
for (Permission perm : role.getPermissions()) {
perms.add(perm.getCode());
}
}
String[] permissions = perms.toArray(new String[perms.size()]);
UserDetails userDetails = org.springframework.security.core.userdetails.User
.withUsername(user.getUsername())
.password(user.getPassword())
.authorities(permissions)
.build();
return userDetails;
}
}
UserDao
@Repository
public interface UserDao {
//按照姓名查询
@Select("select * from pe_user where username = #{username}")
User findUserByName(String name);
//级联查询(按照id查询)
@Results({
@Result(column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(column = "salt", property = "salt"),
@Result(column = "id", property = "roles",
many = @Many(select = "com.cc.springboot3.dao.RoleDao.findRoleById"))
})
@Select("select * from pe_user where id = #{id}")
User findUserById(String id);
}
RoleDao
@Repository
public interface RoleDao {
//级联查询
@Results({
@Result(column = "id", property = "id"),
@Result(column = "name", property = "name"),
@Result(column = "code", property = "code"),
@Result(column = "description", property = "description"),
@Result(column = "id", property = "permissions",
many = @Many(select = "com.cc.springboot3.dao.PermissionDao.findPermissionById"))
})
@Select("select * from pe_role where id in (select role_id from pe_user_role where user_id = #{id})")
Set<Role> findRoleById(String id);
}
PermissionDao
@Repository
public interface PermissionDao {
//级联查询
@Results({
@Result(column = "id", property = "id"),
@Result(column = "name", property = "name"),
@Result(column = "code", property = "code"),
@Result(column = "description", property = "description")
})
@Select("select * from pe_permission where id in (select permission_id from pe_role_permission where role_id = #{id})")
Set<Permission> findPermissionById(String id);
}
实体类
User
@Getter
@Setter
@Data
public class User implements Serializable {
private String id;
private String username;
private String password;
private String salt;
private Set<Role> roles = new HashSet<Role>();//用户与角色 多对多
}
Role
@Getter
@Setter
@Data
public class Role implements Serializable {
private static final long serialVersionUID = 594829320797158219L;
private String id;
private String code;
private String name;
private String description;
//角色与权限 多对多
private Set<Permission> permissions = new HashSet<Permission>(0);
}
Permission
@Getter
@Setter
@NoArgsConstructor
@Data
public class Permission implements Serializable {
private static final long serialVersionUID = -4990810027542971546L;
private String id;
private String name;
private String code;
private String description;
}
配置类
WebSecurityConfig
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncode(){
return new BCryptPasswordEncoder();
}
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
// .antMatchers("/r/r1").hasAuthority("p1")
// .antMatchers("/r/r2").hasAuthority("p2")
// .antMatchers("/user").hasAuthority("user-add")
.antMatchers("/r/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.successForwardUrl("/login-success");
}
}
最后配置一下数据源与mybastis
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/shiro?serverTimezone=GMT
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
configuration:
map-underscore-to-camel-case: true
type-aliases-package: com.cc.domain
启动类添加@EnableGlobalMethodSecurity注解
/**
* @author CC
* 项目演示:项目鉴权
* 方式1:内容鉴权
* 保护URL常用的方法有:
* authenticated() 保护URL,需要用户登录
* permitAll() 指定URL无需保护,一般应用与静态资源文件
* hasRole(String role) 限制单个角色访问,角色将被增加 “ROLE_” .所以”ADMIN” 将和 “ROLE_ADMIN”进行比较.
* hasAuthority(String authority) 限制单个权限访问
* hasAnyRole(String… roles)允许多个角色访问.
* hasAnyAuthority(String… authorities) 允许多个权限访问.
* access(String attribute) 该方法使用 SpEL表达式, 所以可以创建复杂的限制.
* hasIpAddress(String ipaddressExpression) 限制IP地址或子网
* 方式2:方法鉴权
* 实现步骤:
* a.@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)开启对应注解支持
* b.
* @PreAuthorize方法前鉴权
* @PostAuthorize方法后鉴权
* @Secured关键字鉴权不建议使用
**/
@MapperScan("com.cc.springboot3.dao")
@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)//权限注解
public class Springboot3Application {
public static void main(String[] args) {
SpringApplication.run(Springboot3Application.class, args);
}
}
数据库我有上传 或者在shiro案例中有数据库详情可以自己创建
这个使用的是SpringSecurity提供的登录页面需要联网 访问有些慢
密码加密的话也是完全由框架提供 所以数据库中也不需要存储盐值
这里有一个加密的测试类
用于给数据库 存储密文
@SpringBootTest
class Springboot3ApplicationTests {
@Test
void test1() {
String hashpw = BCrypt.hashpw("123", BCrypt.gensalt());
System.out.println(hashpw);
// $2a$10$pOjRRLkRIfHYGcAAZ.qciuHh5ie5ITklFjmNXBEwo/pBDzF45MhJ.
boolean checkpw = BCrypt.checkpw("123", "$2a$10$dx7Mh9ZCSD97wmLYSul8qeaOhz950dnTyW9XR/YgaavS0FlIH.U9C");
System.out.println(checkpw);
}
}
总的来说 相比shiro的话还是非常简单 方便