zoukankan      html  css  js  c++  java
  • spring-boot启用security组件

    前言

    从今天开始,我打算系统地回顾下spring-boot的相关知识,但是在系统学习之前,我想先把之前没有了解过的知识过一遍,之后再系统地总结。今天我们就先来看下spring-boot的官方组件secutity,下面我们就直接开始吧!

    Security组件

    这个组件是spring-boot的基础组件之一,主要用于spring-boot项目的权限控制,我们今天主要是看下它的基础配置和一些简单应用。

    开始之前,我们要先创建一个spring-boot项目。

    创建项目

    项目的依赖很简单,最核心的依赖就两个,一个就是spring-boot-starter,这个依赖是spring-boot最基础的依赖,没有之一,但凡你创建spring-boot项目都会有这个依赖;

    另外一个核心依赖就是我们今天的主角——spring-boot-starter-security

    除了两个核心依赖,我还引入了guava的依赖,这是一个谷歌出品的工具类包,其中有很多特别方便的工具类,比如容器操作。

    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>30.1.1-jre</version>
        <!-- or, for Android: -->
        <!--<version>30.1.1-android</version>-->
    </dependency>
    

    加入以上配置之后,我们不需要做任何配置,security其实已经被我们集成到spring-boot中了,不信你启动下看看:

    如果你的控制台也有如上信息,说明你的spring-boot项目已经集成了security,最上面打印的就是我们的登录密码,用户名默认情况下是user,下面我们简单测试下。

    测试

    首先,我们要写一个controller,没有controller的话,确实不好测试。controller中,我就写了一个简单的testSecurity方法,方法内部打印helle信息。

    @RestController
    @RequestMapping("/test")
    public class TestController {
    
        @GetMapping("security")
        public Object testSecurity(String name) {
            return "hello, " + name;
    
        }
    }
    

    controller创建完成后,我们再次启动项目,然后访问http://localhost:8989/test/security?name=syske

    正常情况下,会跳转到登录页面,这就说明security组件已经起作用了。

    这里登录的用户名是user,密码就是控制台打印出来的密码,输入用户名和密码,然后登录,这时候接口就正常返回了:

    登录成功后,你后面再访问其他接口也是不需要再次登陆的。而且我试过,就算你关闭浏览器,再次打开,也是不需要登陆的,但是你重启spring-boot服务之后,就需要重新登录了,目前还不清楚具体的鉴权原理,从浏览器请求情况来看,不是token,后面研究下。

    security虽然起作用了,但是我们在实际应用的时候,不可能都用user和默认密码登录吧,毕竟不方便,也不合理,所以下面我们就来看戏如何来配置security,让它满足我们更复杂的应用场景。

    配置security

    首先,我们要创建一个配置类,这个配置类要继承WebSecurityConfigurerAdapter,并重写其中的configure方法,这个类有多个configure方法,这里我们重写的是参数为AuthenticationManagerBuilder,其他配置类,我们后面继续讲。

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        private Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
        @Autowired
        private ReaderRepository readerRepository;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(username -> {
                System.out.println(username);
                return readerRepository.loadUserByUsername(username);
                        }).passwordEncoder(new BCryptPasswordEncoder());
        }
    }
    

    这个方法其实就是用户登录时的鉴权方法,我们通过重写这个方法,可以实现我们自己的鉴权操作。我这里现在都是写死的,只要你登录的用户是admin,就可以鉴权通过,密码我也是写死的。

    userDetailsService方法的作用是配置用户信息查询服务,我们需要继承UserDetailsService接口,并实现其中的loadUserByUsername方法,这个方法会返回 UserDetails,也就是用户基本信息,主要是密码和用户名,还有过期时间这些:

    下面是我写的一个构建UserDetails的服务,后期的话,可以根据自己的需要整合数据库。

    @Service
    public class ReaderRepository implements UserDetailsService {
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            if ("admin".equals(username)) {
                return new UserInfo("admin", new BCryptPasswordEncoder()
                        .encode("admin"));
            } else {
                return null;
            }
        }
    
        public static class UserInfo implements UserDetails {
            private String username;
            private String password;
    
            public UserInfo(String username, String password) {
                this.username = username;
                this.password = password;
            }
    
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return Arrays.asList(new SimpleGrantedAuthority("READER"));
            }
    
            @Override
            public String getPassword() {
                return this.password;
            }
    
            @Override
            public String getUsername() {
                return this.username;
            }
    
            @Override
            public boolean isAccountNonExpired() {
                return true;
            }
    
            @Override
            public boolean isAccountNonLocked() {
                return true;
            }
    
            @Override
            public boolean isCredentialsNonExpired() {
                return true;
            }
    
            @Override
            public boolean isEnabled() {
                return true;
            }
        }
    }
    

    然后,重启我们的spring-boot项目,这时候我们就不能用默认的用户名和密码登录了,控制台也不会有密码打印了,而是用我们设置的用户名和密码登录。

    这里需要注意的是,passwordEncoder(new BCryptPasswordEncoder())的作用是指定密码的加密器,这里的加密器必须和你保存密码时用的加密器一致,否则密码校验无法通过。

    如果你不指定密码加密器,鉴权的时候也是会报错的:

    另外,还有一点比较重要,就是我们在登录的时候,其实就是调用userDetailsServiceloadUserByUsername获取用户信息,然后进行鉴权操作,所以如果要修改security组件的相关配置,就必须实现loadUserByUsername方法,这样才能确保你的用户数据是可控的。

    总结

    今天我们分享了spring-boot启用security组件的相关知识点,整个过程还是比较简单,但是由于时间的关系,好些点我们没有展开来讲,也讲的不够细,不过也没有关系,因为最近一段时间我们都打算分享spring-boot相关知识,所以明天我们会继续分享.

    好了,今天的内容就到这里吧,我们明天继续。

  • 相关阅读:
    顺序查找
    折半查找
    KMP
    php长时间的脚本,报502
    AcWing 27. 数值的整数次方
    acwing 25. 剪绳子
    Best Cow Line <挑战程序设计竞赛> 习题 poj 3617
    acwing 23. 矩阵中的路径
    AcWing 34. 链表中环的入口结点
    AcWing 33. 链表中倒数第k个节点
  • 原文地址:https://www.cnblogs.com/caoleiCoding/p/15061264.html
Copyright © 2011-2022 走看看