美文网首页
SpringSecurity的配置详解

SpringSecurity的配置详解

作者: TZX_0710 | 来源:发表于2019-09-18 14:32 被阅读0次

    在上一章的时候解析启动流程源码的时候,已经提到security的配置文件主要来自SpringBootWebSecurityConfiguration里面的WebSecurityConfigurerAdapter类,默认security是创建了一个,那么我们需要自定义可以去创建一个类去继承WebSecurityConfigurerAdapter

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        //配置绕过security验证  不走Spring security
        @Override
        public void configure(WebSecurity web) throws Exception {
            super.configure( web );
            //web.ignoring().antMatchers( "/hello" );
        }
    
        //配置
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
           // super.configure( auth );
            //通过IDEA自带的Java类图看出了UserDetailService的子类InMemoryUserDetailsManager
            //测试方式  给密码添加的时候必须加上{noop}  authorities 或者roles必须添加
            //authorities 此用户的权限
            //roles 此用户的角色
            auth.userDetailsService(new InMemoryUserDetailsManager(
                    User.builder().username("jsbintask1").password("{noop}123456").authorities("jsbintask1").build(),
                    User.builder().username("jsbintask2").password("{noop}123456").authorities("jsbintask2").build()));
        }
    
        //默认配置 是拦截所有的  不采用默认配置 则重写
        @Override
        protected void configure(HttpSecurity http) throws Exception {
           //super.configure( http );
            //loginPage  自定义配置页面
            //loginProcessinUrl登录拦截的URL   security有一个自带的login页面 如果需要自定义登陆页面则重写
            //successForwardUrl  成功登录之后跳转
            http.formLogin()
                    //.loginPage("/index")
                    //.loginProcessingUrl("/login")
                    .successForwardUrl("/hello")
                    .and()
                    .authorizeRequests()
                    //permitAll不饶过安全验证
                    .antMatchers( "/login", "/error", "/favicon.ico").permitAll()
                    //定义哪些请求需要Url需要被保护
                    .anyRequest()
                    .authenticated()
                    .and()
                    .csrf()
                    .disable();
        }
    }
    

    阅读源码:可通过IDEA查看类图

    结合实际应用example
    在原有基础上pom文件引入对mysql支持

     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
    
    
    yml文件编写 
    注意:yml文件最好不要有中文!!因为可能会让你启动报错 input length
    server:
      port: 8080
    spring:
      freemarker:
        enabled: true
        cache: false
        template-loader-path: classpath:/templates/
        suffix: .html
      security:
        user:
          name: user
          password: user
          roles: user,admin
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/security_db?useSSL=false&serverTimezone=UTC
        username: root
        password: root
    #打印sql
      jpa:
        show-sql: true
    #update  jpa的表和数据库的表是对应的  如果实体类有 字段数据库没有字段那么则会修改数据库表结构
    #ID必须有! 实体类 userName  那么数据库对应的就是user_name带下划线的!
        hibernate:
          ddl-auto: update
        properties:
          hibernate:
            formate_sql: true
        #open-in-view 一个小警告无关紧要 但是 强迫症开启了 这样避免了控制台warn提示 作用也就是禁用OSIV (Open Session in View)
        open-in-view: false 
    

    编写所需实体类

    User表 
    @Entity
    @Table
    @Data
    public class User {
        //声明主键策略 自增长
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        private String username;
    
        private String password;
    
        private Integer age;
    
        private String address;
    
        private Integer roleId;
    }
    
    @Entity
    @Table
    @Data
    public class Role {
        //声明主键策略 自增长
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        private String roleName;
    
        private String description;
    }
    
    //因为实际开发中我们的数据都是来自数据库 。security在之前源码中讲解在启动流程的时候会loadinMemory到内存当中 我们在这边重写一下
    @Data
    @AllArgsConstructor //生成全参构造函数
    @NoArgsConstructor  //生成无参构造函数
    public class AuthUser implements UserDetails {
    
        private String userName;
    
        private String password;
    
        private List <Role> roleList;
    
        //返回用户的权限
        @Override
        public Collection <? extends GrantedAuthority> getAuthorities() {
            return roleList.isEmpty() ? Collections.EMPTY_LIST : (
                    roleList.parallelStream().map( role ->
                            new SimpleGrantedAuthority(
                                    role.getRoleName() ) ).collect( Collectors.toList() ));
    
        }
    
        @Override
        public String getPassword() {
            return password;
        }
    
        @Override
        public String getUsername() {
            return userName;
        }
    
        //账户未过期 true  过期false
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
        //账户是否锁定
        //如果为Ture表示用户未被锁定
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        //凭据是否过期  如果为True表示用户的凭据依旧有效
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        //指定用户是启用还是禁用  True表示启用 false表示已停用
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    //编写dao对数据库进行访问
    public interface UserRepository extends JpaRepository<User,Integer> {
    
        //根据用户名查找对象
       User findByUsername(String username);
    }
    
    //Role
    public interface RoleRepository extends JpaRepository<Role,Integer> {
    
    
    }
    
    //重写UserDetailService  前面启动流程的讲解已经说明 如果要自定义实现那么也必须要实现UserDetailService  
    
    @Service
    @Primary
    public class CustomUserDetailsServiceImpl implements UserDetailsService {
    
        private final UserRepository userRepository;
    
        private final RoleRepository roleRepository;
    
        @Autowired
        public CustomUserDetailsServiceImpl(UserRepository userRepository, RoleRepository roleRepository) {
            this.userRepository = userRepository;
            this.roleRepository = roleRepository;
        }
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //
            Function <String, User> findByUserName = userRepository::findByUsername;
            User users = findByUserName.apply( username );
            if(users==null){
                throw new  UsernameNotFoundException("user is not found");
            }
            //返回自定义的usersDetails
            return new AuthUser( users.getUsername(),users.getPassword(),
                    roleRepository.findAllById(Collections.singletonList(users.getRoleId())));
        }
    }
    
    
    
    编写对web端的控制
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        //配置绕过security验证  不走Spring security
        @Override
        public void configure(WebSecurity web) throws Exception {
            super.configure( web );
            web.ignoring().antMatchers( "/hello" );
        }
    
        //配置
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            super.configure( auth );
            //通过IDEA自带的Java类图看出了UserDetailService的子类InMemoryUserDetailsManager
            //测试方式  给密码添加的时候必须加上{noop}  authorities 或者roles必须添加
            //authorities 此用户的权限
            //roles 此用户的角色
          /*  auth.userDetailsService(new InMemoryUserDetailsManager(
                    User.builder().username("jsbintask1").password("{noop}123456").authorities("jsbintask1").build(),
                    User.builder().username("jsbintask2").password("{noop}123456").authorities("jsbintask2").build()));
    */    }
    
        //默认配置 是拦截所有的  不采用默认配置 则重写
        @Override
        protected void configure(HttpSecurity http) throws Exception {
           //super.configure( http );
            //loginPage  自定义配置页面
            //loginProcessinUrl登录拦截的URL   security有一个自带的login页面 如果需要自定义登陆页面则重写
            //successForwardUrl  成功登录之后跳转
            http.formLogin()
                    //.loginPage("/index")
                    //.loginProcessingUrl("/login")
                    .successForwardUrl("/hello")
                    .and()
                    .authorizeRequests()
                    //permitAll不饶过安全验证
                    .antMatchers( "/login", "/error", "/favicon.ico").permitAll()
                    //定义哪些请求需要Url需要被保护
                    .anyRequest()
                    .authenticated()
                    .and()
                    .csrf()
                    .disable();
        }
    }
    

    然后可以输入数据库录入的用户信息和密码

    image.png

    发现启动报错


    image.png
    image.png

    原因是security的密码是加过密的!!!加过密的!
    所以我们需要注入一个加密Bean进去

    @Configuration
    public class Security_Other_Bean {
    
        //密码加密配置
        @Bean
        public BCryptPasswordEncoder bCryptPasswordEncoder(){
            return new BCryptPasswordEncoder(  );
        }
    }
    

    重新登陆搞定 OK !

    相关文章

      网友评论

          本文标题:SpringSecurity的配置详解

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