• 认证和授权学习2:springboot中快速使用spring security


    认证和授权学习2:springboot中快速使用spring security

    本文以一个示例工程记录下如何在springboot工程中快速的使用spring security,使用的springboot版本是
    2.1.3.RELEASE

    一、创建工程,导入依赖

    创建一个springboot工程,导入springsecurity的起步依赖.

           <!-- 以下是>spring boot依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- 以下是>spring security依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
    

    二、默认配置

    这个时候启动应用,这个应用就已经被保护了,springsecurity提供了一个默认用户user,对应的密码在启动工程时会打印在控制台上,如

    Using generated security password: c07618df-93d6-4d0c-88df-9c373d2131e3
    

    这个时候访问应用中的一个资源,就会跳转到springsecurity默认的一个登录页面,输入账号密码后会跳转到登录前要访问的url

    三、自定义配置

    主要涉及2个方面,用户配置,安全配置,通过创建一个配置类继承WebSecurityConfigurerAdapter来配置

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        //1.用户配置
        //2.安全配置
    }
    

    3.1用户配置

    配置时springsecurity提供了两种用户配置,简单点的可以直接在内存中配置用户对象,用于测试;也可以连接数据库进行持久化配置

    3.1.1 在内存中配置用户

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        //1.用户配置
        @Bean
        public UserDetailsService userDetailsService() {
            InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
            manager.createUser(User.withUsername("lyy").password("123").authorities("ROLE_p1").build());
            manager.createUser(User.withUsername("zs").password("123").authorities("ROLE_ADMIN").build());
            return manager;
        }
        //1.1用户密码的加密方式
        @Bean
        public PasswordEncoder passwordEncoder(){
            return NoOpPasswordEncoder.getInstance();
            //return new BCryptPasswordEncoder();
        }
        //2.安全配置
    }
    

    springsecurity提供了一个InMemoryUserDetailsManager对象来在内存中创建用户。在上边的代码中,创建了两个用户并赋予不同的权限。

    需要注意的是,要配置验证用户密码时使用的加密方式,如果不想加密,可以配置NoOpPasswordEncoder的对象,表示不加密。

    3.1.2 使用数据库中的用户对象

    springsecurity提供了一个UserDetailsService接口来查询用户,要从数据库查询用户,只需要创建一个这个接口的bean并加入spring容器中,然后移除内存用户的相关配置,但编码器还要保留。

    @Component
    public class MyUserDetailService implements UserDetailsService {
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            //模拟从数据库查询用户信息,这里这个UserDetails中的用户信息都是从数据库查询到的
            System.out.println("当前请求登录的用户:"+username);
            UserDetails userDetails = User.withUsername(username).password("111")
                    .authorities("p1").build();
            return userDetails;
        }
    }
    

    实际上就是实现了loadUserByUsername方法,返回了一个UserDetails对象给springsecurity

    3.2安全配置

    安全配置通过重写configure方法来实现。主要设置这几个方面

    (1)哪些url被保护,需要什么权限才能访问。这里要注意的是,用hasRole指定角色时不带ROLE_前缀,但是配置用户时要带上ROLE_前缀。匹配url时,越具体的url要先匹配。

    (2)配置登录页面和处理登录请求的url,注意自定义安全配置时一定要把登录页面和登录url配上,不然访问任何页面都是403,除非最后一行调用父类的config方法

    (3)退出和失效的相关配置.

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        //1.用户配置
        ...
        //2.安全配置
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            /**
             * 设置对url的保护时,更具体的规则应该先写,模糊匹配的要写在最后,
             * 因为一次请求匹配到第一个规则后就会忽略后边的规则
             */
    
            http.csrf().disable();
            //这两个资源要有特定的权限才可以访问
            http.authorizeRequests().antMatchers("/r/r1").hasRole("p1");
            http.authorizeRequests().antMatchers("/r/r2").hasRole("p2");
            //配置这个目录下的资源要登录才可以访问,不配置的话不拦截,不登录页可以访问
            http.authorizeRequests().antMatchers("/r/**").authenticated();
            http.authorizeRequests().anyRequest().permitAll();
            //因为下边这个配置针对的url在上边那个配置已经匹配过了,所以下边这个不生效
            http.authorizeRequests().antMatchers("/test1.html").authenticated();
            http.formLogin()
                    .loginPage("/login.html")
                    //处理登录请求的url
                    .loginProcessingUrl("/login");
                    //登录成功后的跳转url,如果不配置,默认跳转到登录前要访问的页面
                    //.successForwardUrl("/login-success");
            //这个配置配置的是多个人登录同一账号时,后边的把前边的挤掉后,把前边的重定向到的页面
            http.sessionManagement().maximumSessions(1).expiredUrl("/sessionExpired.html");
            //这个配置退出的url和退出后跳转到的页面
            http.logout().logoutUrl("/mylogout").logoutSuccessUrl("/logoutSuccess.html");
        }
    }
    

    注意这里所有的html页面都放在springboot的静态资源目录中,这样才能被访问到,我是放在了resources/static目录。

    登录页面的内容如下

    <html>
    <head>
        <meta charset="UTF-8">
        <title>login</title>
    </head>
    <body>
    login
    <form action="login" method="post">
        用户名:<input type="text" name="username"><br>
        密&nbsp;&nbsp;&nbsp;码:
        <input type="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
    </body>
    </html>
    
    

    注意这里登录表单的action写的是相对路径,如果要写绝对路径,就要带上当前应用的路径,即yml中的配置

    server:
      port: 8080
      servlet:
        context-path: /springsecurity-springboot01
    

    可以在这里查看完整的示例工程

    示例工程

  • 相关阅读:
    LeetCode 50: Pow(x, n)
    Codility 1: equilibrium
    LeetCode 49: Anagrams
    crackme160--(5)
    crackme160--(4)
    魔兽显血改键工具的脱壳和修改
    crackme160--(3)
    crackme160--(1)
    python-装饰器
    编程语言C++01-C++入门学习路线
  • 原文地址:https://www.cnblogs.com/chengxuxiaoyuan/p/13941893.html
Copyright © 2020-2023  润新知