首页 > 技术文章 > SpringBoot+Mybatis+PostMan(七):用户角色权限访问控制入门(数据模拟实现,不带数据库)

yeyuting 2021-01-22 09:54 原文

Springboot+Mybatis+redis+postman项目实战总目录*

第二篇章:用户角色权限访问控制

SpringBoot+Mybatis+PostMan(八):用户角色权限访问控制一(数据库用户角色表查询组合)

SpringBoot+Mybatis+PostMan(九):用户角色权限访问控制二(加入资源表和资源角色对应表)

SpringBoot+Mybatis+PostMan(十):用户角色权限访问控制三(禁用session、启用token并集成redis)

 

继上一个项目Springboot+Mybatis+redis+postman项目实战总目录*实现用户session认证登陆后,我们紧接着对用户角色进行控制,用于实现不同觉得访问不同的接口,对于没有给到权限的角色实现禁止访问功能。在实现此功能前,我们先做一个热身项目,先不连接数据库,模拟一下数据库操作实现角色控制,这里我们主要实现employ角色和admin以不同角色实现不同页面访问,作为后面课程的入门。

 

项目源码下载地址:https://github.com/yeyuting-1314/JavaGoGoGo.git

 

项目目录如下:

先做一下准备工作。

一、准备工作

1. 新建一个spring boot项目,然后导入相应依赖。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

2. 实体类生成:

Admin类代码如下所示:
/**
 * @author yeyuting
 * @create 2021/1/21
 */
public class Admin {

    private String username;

    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
Employee 类代码如下:
/**
 * @author yeyuting
 * @create 2021/1/21
 */
public class Employee {
    private String id;
    private String username;
    private String password;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

二、正餐开始

1. 继承WebSecurityConfigurerAdapter配置角色权限

/**
 * @author yeyuting
 * @create 2021/1/21
 */
@Configuration
@EnableWebSecurity
//WebSecurityConfigurerAdapter 类是个适配器, 在配置的时候,需要我们自己写个配置类去继承他,然后编写自己所特殊需要的配置
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {


    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());//passwoldEncoder是对密码的加密处理,如果user中密码没有加密,则可以不加此方法。注意加密请使用security自带的加密方式。
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()//禁用了 csrf 功能
                .authorizeRequests()//限定签名成功的请求
                .antMatchers("/decision/**","/govern/**","/employee/*").hasAnyRole("EMPLOYEE","ADMIN")//对decision和govern 下的接口 需要 USER 或者 ADMIN 权限
                .antMatchers("/employee/login").permitAll()///employee/login 不限定
                .antMatchers("/admin/**").hasRole("ADMIN")//对admin下的接口 需要ADMIN权限
                .antMatchers("/oauth/**").permitAll()//不拦截 oauth 开放的资源
                .anyRequest().permitAll()//其他没有限定的请求,允许访问
                .and().anonymous()//对于没有配置权限的其他请求允许匿名访问
                .and().formLogin()//使用 spring security 默认登录页面
                .and().httpBasic();//启用http 基础验证

    }

}

2. 声明实现类,用于实现接住前端post传输过去的数据,并进行权限访问,从而给到相应对象相应的角色,从而访问到不同页面。

/**
 * @author yeyuting
 * @create 2021/1/21
 */
@Service
/*
* 用户在登录时 Spring Security 会通过 UserDetailsService.loadUserByUsername() 方法获取登录的用户的详细信息,
* 然后会将用户的数据封装进 UserDetails 对象中,因此这里需要实现UserDetailsService接口,并重写loadUserByUsername方法
* */
public class UserDetailServiceImpl implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //角色和权限共用GrantedAuthority接口,后面采集到的角色信息将存储到grantedAuthorities集合中
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        //生成环境是查询数据库获取username的角色用于后续权限判断(如:张三 admin)
        //这里暂时先不做数据库操作,给定假数据,我们后面再加入数据库
        if (username.equals("employee")) {
            Employee employee = new Employee();
            employee.setUsername("employee");
            employee.setPassword("123456");
            //对employ对象赋予ROLE_EMPLOYEE角色,存储到grantedAuthority中
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_EMPLOYEE");
            //将已经被赋予角色的grantedAuthority存储到grantedAuthorities集合中
            grantedAuthorities.add(grantedAuthority);
            //创建一个用户,用于判断权限,请注意此用户名和方法参数中的username一致;BCryptPasswordEncoder是用来演示加密使用。
            //这里主要是实现用户名和密码的核对,如果信息都正确才给开这个权限,这是一种安全策略
            return new User(employee.getUsername(), new BCryptPasswordEncoder().encode(employee.getPassword()), grantedAuthorities);
        }
        if (username.equals("admin")) {
            Admin admin = new Admin();
            admin.setUsername("admin");
            admin.setPassword("123456");
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_ADMIN");
            grantedAuthorities.add(grantedAuthority);
            return new User(admin.getUsername(), new BCryptPasswordEncoder().encode(admin.getPassword()), grantedAuthorities);
        }
        else {
            return null;
        }


    }
}

3.接下来实现业务层

AdminController类:

/**
 * @author yeyuting
 * @create 2021/1/21
 */
@RestController
@RequestMapping("/admin")
public class AdminController {


    @GetMapping("/greeting")
    public String greeting() {
        return "Hello,World!";
    }

    @GetMapping("/login")
    public String login() {

        return "login sucess";
    }
}

4. EmployeeController类: 

/**
 * @author yeyuting
 * @create 2021/1/21
 */
@RestController
@RequestMapping("/employee")
public class EmployeeController {


    @GetMapping("/greeting")
    public String greeting() {
        return "Hello,World!";
    }

    @GetMapping("/login")
    public String login() {

        return "login sucess";
    }
}

三、正餐结束,接下里启动项目,前端post测试看看结果如何

1. 如果是employ角色访问自己的页面,访问成功

 

 2. 如果是employ角色访问admin的页面,访问失败

 

 3. 如果是admin角色访问admin的页面,访问成功

 

 4. 如果是admin角色访问employee的页面,访问成功

 

 这样一来,我们的角色控制入门就完成了,此项目灵感来源于文章https://www.jianshu.com/p/6a7dcef02bd5,十分的感谢,要不是这篇文章,我后面的数据库嵌入可能不会这么顺利的实现。

至此,结束。

推荐阅读