美文网首页
SpringBoot 整合 SpringSecurity(权限控

SpringBoot 整合 SpringSecurity(权限控

作者: 索性流年 | 来源:发表于2020-06-11 18:24 被阅读0次

来自蚂蚁课堂
链接:http://www.mayikt.com/

概述

  • Spring Security是Spring提供的一个安全框架,提供认证和授权功能,为应用系统提供声明式的安全访问控制,减少了企业为系统安全控制的大量、重复代码。

SpringSecurity 应用场景

  1. 权限控制
  2. 身份认证

RBAC权限表设计

图片.png

pom 引入依赖

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

yml 配置

# 配置freemarker
spring:
  freemarker:
    # 设置模板后缀名
    suffix: .ftl
    # 设置文档类型
    content-type: text/html
    # 设置页面编码格式
    charset: UTF-8
    # 设置页面缓存
    cache: false
    # 设置ftl文件路径
    template-loader-path:
      - classpath:/templates
  # 设置静态文件路径,js,css等
  mvc:
    static-path-pattern: /static/**
  datasource:
    name: test
    url: jdbc:mysql://127.0.0.1:3306/mayikt_rbac
    username: root
    password: root
    # druid 连接池
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver

实现 WebSecurityConfigurerAdapter

@Component
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MemberUserDetailsService memberUserDetailsService;
    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 添加授权账户
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        // 设置用户账号信息和权限
//        auth.inMemoryAuthentication().withUser("mayikt_admin").password("mayikt")
//                .authorities("addMember", "delMember", "updateMember", "showMember");
//        // 如果mayikt_admin账户权限的情况 所有的接口都可以访问,如果mayikt_add 只能访问addMember
//        auth.inMemoryAuthentication().withUser("mayikt_add").password("mayikt")
//                .authorities("addMember");
        auth.userDetailsService(memberUserDetailsService).passwordEncoder(new PasswordEncoder() {
            /**
             * 对密码MD5
             * @param rawPassword
             * @return
             */
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String) rawPassword);
            }

            /**
             * rawPassword 用户输入的密码
             * encodedPassword 数据库DB的密码
             * @param rawPassword
             * @param encodedPassword
             * @return
             */
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                String rawPass = MD5Util.encode((String) rawPassword);
                boolean result = rawPass.equals(encodedPassword);
                return result;
            }
        });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        //配置httpBasic Http协议认证
////        http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
//        //配置httpBasic Http协议认证
//        http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and()
//                .formLogin();
//        // 默认fromLog
        List<PermissionEntity> allPermission = permissionMapper.findAllPermission();
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
                expressionInterceptUrlRegistry = http.authorizeRequests();
        allPermission.forEach((permission) -> {
            expressionInterceptUrlRegistry.antMatchers(permission.getUrl()).
                    hasAnyAuthority(permission.getPermTag());

        });
        expressionInterceptUrlRegistry.antMatchers("/login").permitAll()
                .antMatchers("/**").fullyAuthenticated()
                .and().formLogin().loginPage("/login").and().csrf().disable();
        //.antMatchers("/addMember") 配置addMember请求权限 hasAnyAuthority("addMember")

    }

    /**
     * There is no PasswordEncoder mapped for the id "null"
     * 原因:升级为Security5.0以上密码支持多中加密方式,恢复以前模式
     *
     * @return
     */
    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }

}

Controller

@RestController
public class ErrorController {
    @RequestMapping("/error/403")
    public String error403() {
        return "您当前访问的接口权限不足.";
    }
}

@Controller
public class IndexController {
    /**
     * 跳转到首页
     *
     * @return
     */
    @RequestMapping("/")
    public String index() {
        return "index";
    }

    @ResponseBody
    @RequestMapping("/addMember")
    public String addMember() {
        return "新增用户";
    }

    @ResponseBody
    @RequestMapping("/delMember")
    public String delMember() {
        return "删除用户";
    }

    @ResponseBody
    @RequestMapping("/updateMember")
    public String updateMember() {
        return "修改用户";
    }

    @ResponseBody
    @RequestMapping("/showMember")
    public String showMember() {
        return "查询用户";
    }


}

自定义SpringBoot 错误异常

@Configuration
public class WebServerAutoConfiguration {
    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/error/400");
        ErrorPage errorPage401 = new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/401");
        ErrorPage errorPage403 = new ErrorPage(HttpStatus.FORBIDDEN, "/error/403");
        ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
        ErrorPage errorPage415 = new ErrorPage(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "/error/415");
        ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
        factory.addErrorPages(errorPage400, errorPage401, errorPage403, errorPage404, errorPage415, errorPage500);
        return factory;
    }
}

实现 UserDetailsService

@Component
@Slf4j
public class MemberUserDetailsService implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;

    /**
     * loadUserByUserName
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1.根据该用户名称查询在数据库中是否存在
        UserEntity userEntity = userMapper.findByUsername(username);
        if (userEntity == null) {
            return null;
        }
        // 2.查询对应的用户权限
        List<PermissionEntity> listPermission = userMapper.findPermissionByUsername(username);
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        listPermission.forEach(user -> {
            authorities.add(new SimpleGrantedAuthority(user.getPermTag()));
        });
        log.info(">>>authorities:{}<<<", authorities);
        // 3.将该权限添加到security
        userEntity.setAuthorities(authorities);
        return userEntity;
    }
}

Dao

public interface UserMapper {
    /**
     * 根据用户名称查询
     *
     * @param userName
     * @return
     */
    @Select(" select * from sys_user where username = #{userName}")
    UserEntity findByUsername(@Param("userName") String userName);

    /**
     * 查询用户的权限根据用户查询权限
     *
     * @param userName
     * @return
     */
    @Select(" select permission.* from sys_user user" + " inner join sys_user_role user_role"
            + " on user.id = user_role.user_id inner join "
            + "sys_role_permission role_permission on user_role.role_id = role_permission.role_id "
            + " inner join sys_permission permission on role_permission.perm_id = permission.id where user.username = #{userName};")
    List<PermissionEntity> findPermissionByUsername(@Param("userName") String userName);
}
public interface PermissionMapper {

    @Select(" select * from sys_permission ")
    List<PermissionEntity> findAllPermission();

}

Entity

//权限表
@Data
public class PermissionEntity {
    private Integer id;
    // 权限名称
    private String permName;
    // 权限标识
    private String permTag;
    // 请求url
    private String url;
}

// 角色信息表
@Data
public class RoleEntity {
    private Integer id;
    private String roleName;
    private String roleDesc;
}

// 用户信息表
@Data
public class UserEntity implements UserDetails {

    private Integer id;
    private String username;
    private String realname;
    private String password;
    private Date createDate;
    private Date lastLoginTime;
    private boolean enabled;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    // 用户所有权限
    private List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    public Collection<? extends GrantedAuthority> getAuthorities() {

        return authorities;
    }

}

相关文章