【SpringSecurity】Springboot整合SpringSecurity中间件(案例)

本文详细描述了如何在SpringBoot项目中整合SpringSecurity,通过预授权注解实现基于角色和权限的API访问控制,相比于Shiro,操作更加简便。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个与我前面写的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的话还是非常简单 方便 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值