第六节 使用注解实现权限控制

亮子 2021-07-19 09:43:34 17540 0 0 0

1、增加注解

Spring Security 配置类开启权限控制注解,即 @EnableGlobalMethodSecurity(prePostEnabled = true)。

package com.shenmazong.config;

import com.shenmazong.security.MyAuthenticationEntryPoint;
import com.shenmazong.security.MyAuthenticationProvider;
import lombok.extern.slf4j.Slf4j;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author 军哥
 * @version 1.0
 * @description: TODO
 * @date 2022/3/8 14:34
 */

@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyAuthenticationProvider myAuthenticationProvider;

    @Autowired
    MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    /**
     * @description 定义密码的加密算法
     * @author 军哥
     * @date 2022/3/8 14:57
     * @version 1.0
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

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

    /**
     * @description 主要是确认权限
     * @author 军哥
     * @date 2022/3/8 14:36
     * @version 1.0
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login", "/").permitAll()
                .anyRequest().authenticated()
                // 设定登录相关页面
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/process")
                .successForwardUrl("/success").
                failureForwardUrl("/failure")
                // 跨域請求关闭
                .and().csrf().disable()
                // 资源下载权限关闭
                .headers().frameOptions().disable();
    }

    /**
     * @description 用户密码验证
     * @author 军哥
     * @date 2022/3/8 14:58
     * @version 1.0
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        log.info("configure:AuthenticationManagerBuilder = ");

        // 使用自定义的验证类
        auth.authenticationProvider(myAuthenticationProvider);

//        // 设置密码加密算法
//        auth.inMemoryAuthentication().passwordEncoder(passwordEncoder());
//
//        //
//        // 设置密码
//        auth.inMemoryAuthentication()
//                .withUser("david").password(passwordEncoder().encode("123456")).authorities("select","add")
//                .and()
//                .withUser("admin").password(passwordEncoder().encode("123456")).authorities("select", "add", "update");
    }
}

2、定义4个接口

   @PreAuthorize("hasAuthority('select')")
    @PostMapping(value = "/select")
    public Object select() {
        log.info("select ...");
        return "select";
    }

    @PreAuthorize("hasAuthority('insert')")
    @PostMapping(value = "/insert")
    public Object insert() {
        log.info("insert ...");
        return "insert";
    }

    @PreAuthorize("hasAuthority('delete')")
    @PostMapping(value = "/delete")
    public Object delete() {
        log.info("delete ...");
        return "delete";
    }

    @PreAuthorize("hasAuthority('update')")
    @PostMapping(value = "/update")
    public Object update() {
        log.info("update ...");
        return "update";
    }

3、赋予不同权限

package com.shenmazong.demosecurity0718.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;

/**
 * @author 军哥
 * @version 1.0
 * @description: TODO
 * @date 2021/7/19 10:36
 */

@Component
@Slf4j
public class MyAuthenticationProvider implements AuthenticationProvider {

    /**
     * @description 自定义验证用户名和密码
     * @author 军哥
     * @date 2021/7/19 10:54
     * @version 1.0
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        log.info("authenticate:来登录了");

        //--1 表单输入的用户名和密码
        String username = (String) authentication.getPrincipal();
        String password = (String) authentication.getCredentials();
        log.info("username={},password={}", username, password);

        if(!username.equals("david")) {
            throw new BadCredentialsException("用户不存在!");
        }

        if(!password.equals("123456")) {
            throw new BadCredentialsException("密码不正确!");
        }

        MyUserDetail user = new MyUserDetail();
        user.setUserName(username);
        user.setUserPass(password);

        MyRole myRole = new MyRole();
        myRole.setRoleName("select");

        ArrayList<MyRole> myRoles = new ArrayList<>();
        myRoles.add(myRole);

        user.setUserRoles(myRoles);


        return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
    }

    /**
     * @description 如果该AuthenticationProvider支持传入的Authentication对象,则返回true
     * @author 军哥
     * @date 2021/7/19 10:54
     * @version 1.0
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

4、权限注解表达式

    // @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
    // @PreAuthorize("hasRole('INSERT')")

    // @PreAuthorize("hasAuthority('sys:dept:delete')")
    // @PreAuthorize(value="isAuthenticated()")//添加登录权限判断,登录才可以调用