美文网首页
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;
        }
    
    }
    
    

    相关文章

      网友评论

          本文标题:SpringBoot 整合 SpringSecurity(权限控

          本文链接:https://www.haomeiwen.com/subject/empnzhtx.html