zoukankan      html  css  js  c++  java
  • Spring Security(二) —— Guides

    摘要: 原创出处 https://www.cnkirito.moe/spring-security-2/ 「老徐」欢迎转载,保留摘要,谢谢!



    上一篇文章《Spring Security(一)–Architecture Overview》,我们介绍了Spring Security的基础架构,这一节我们通过Spring官方给出的一个guides例子,来了解Spring Security是如何保护我们的应用的,之后会对进行一个解读。

    2 Spring Security Guides

    2.1 引入依赖

     1 <dependencies>
     2     <dependency>
     3         <groupId>org.springframework.boot</groupId>
     4         <artifactId>spring-boot-starter-web</artifactId>
     5     </dependency>
     6     <dependency>
     7         <groupId>org.springframework.boot</groupId>
     8         <artifactId>spring-boot-starter-security</artifactId>
     9     </dependency>
    10     <dependency>
    11         <groupId>org.springframework.boot</groupId>
    12         <artifactId>spring-boot-starter-thymeleaf</artifactId>
    13     </dependency>
    14 </dependencies>

    2.2 创建一个不受安全限制的web应用由于我们集成了springboot,所以不需要显示的引入Spring Security文档中描述core,config依赖,只需要引入spring-boot-starter-security即可。

    这是一个首页,不受安全限制

    src/main/resources/templates/home.html

     1 <!DOCTYPE html>
     2 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
     3     <head>
     4         <title>Spring Security Example</title>
     5     </head>
     6     <body>
     7         <h1>Welcome!</h1>
     8 
     9         <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    10     </body>
    11 </html>

    src/main/resources/templates/hello.html这个简单的页面上包含了一个链接,跳转到”/hello”。对应如下的页面

     1 <!DOCTYPE html>
     2 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
     3       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
     4     <head>
     5         <title>Hello World!</title>
     6     </head>
     7     <body>
     8         <h1>Hello world!</h1>
     9     </body>
    10 </html>
     1 @Configuration
     2 public class MvcConfig extends WebMvcConfigurerAdapter {
     3 
     4     @Override
     5     public void addViewControllers(ViewControllerRegistry registry) {
     6         registry.addViewController("/home").setViewName("home");
     7         registry.addViewController("/").setViewName("home");
     8         registry.addViewController("/hello").setViewName("hello");
     9         registry.addViewController("/login").setViewName("login");
    10     }
    11 
    12 }

    2.3 配置Spring Security接下来配置Spring MVC,使得我们能够访问到页面。

    一个典型的安全配置如下所示:

     1 @Configuration
     2 @EnableWebSecurity <1>
     3 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { <1>
     4     @Override
     5     protected void configure(HttpSecurity http) throws Exception {
     6         http <2>
     7             .authorizeRequests()
     8                 .antMatchers("/", "/home").permitAll()
     9                 .anyRequest().authenticated()
    10                 .and()
    11             .formLogin()
    12                 .loginPage("/login")
    13                 .permitAll()
    14                 .and()
    15             .logout()
    16                 .permitAll();
    17     }
    18 
    19     @Autowired
    20     public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    21         auth <3>
    22             .inMemoryAuthentication()
    23                 .withUser("admin").password("admin").roles("USER");
    24     }
    25 }

    <2> configure(HttpSecurity)定义了哪些URL路径应该被拦截,如字面意思所描述:”/“, “/home”允许所有人访问,”/login”作为登录入口,也被允许访问,而剩下的”/hello”则需要登陆后才可以访问。<1> @EnableWebSecurity注解使得SpringMVC集成了Spring Security的web安全支持。另外,WebSecurityConfig配置类同时集成了WebSecurityConfigurerAdapter,重写了其中的特定方法,用于自定义Spring Security配置。整个Spring Security的工作量,其实都是集中在该配置类,不仅仅是这个guides,实际项目中也是如此。

    <3> configureGlobal(AuthenticationManagerBuilder)在内存中配置一个用户,admin/admin分别是用户名和密码,这个用户拥有USER角色。

    我们目前还没有登录页面,下面创建登录页面:

     1 <!DOCTYPE html>
     2 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
     3       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
     4     <head>
     5         <title>Spring Security Example </title>
     6     </head>
     7     <body>
     8         <div th:if="${param.error}">
     9             Invalid username and password.
    10         </div>
    11         <div th:if="${param.logout}">
    12             You have been logged out.
    13         </div>
    14         <form th:action="@{/login}" method="post">
    15             <div><label> User Name : <input type="text" name="username"/> </label></div>
    16             <div><label> Password: <input type="password" name="password"/> </label></div>
    17             <div><input type="submit" value="Sign In"/></div>
    18         </form>
    19     </body>
    20 </html>

    最后,我们为hello.html添加一些内容,用于展示用户信息。这个Thymeleaf模板提供了一个用于提交用户名和密码的表单,其中name=”username”,name=”password”是默认的表单值,并发送到“/ login”。 在默认配置中,Spring Security提供了一个拦截该请求并验证用户的过滤器。 如果验证失败,该页面将重定向到“/ login?error”,并显示相应的错误消息。 当用户选择注销,请求会被发送到“/ login?logout”。

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
        <head>
            <title>Hello World!</title>
        </head>
        <body>
            <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
            <form th:action="@{/logout}" method="post">
                <input type="submit" value="Sign Out"/>
            </form>
        </body>
    </html>

    2.4 添加启动类我们使用Spring Security之后,HttpServletRequest#getRemoteUser()可以用来获取用户名。 登出请求将被发送到“/ logout”。 成功注销后,会将用户重定向到“/ login?logout”。

    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) throws Throwable {
            SpringApplication.run(Application.class, args);
        }
    
    }

    访问首页http://localhost:8080/:2.5 测试

    home.htmlhome.html

    点击here,尝试访问受限的页面:/hello,由于未登录,结果被强制跳转到登录也/login

    login.htmllogin.html

    输入正确的用户名和密码之后,跳转到之前想要访问的/hello:

    hello.htmlhello.html

    点击Sign out退出按钮,访问:/logout,回到登录页面:

    logout.htmllogout.html

    Spring Security 无法登陆,报错:There is no PasswordEncoder mapped for the id “null”

    网上百度了一下发现这是因为Spring security 5.0中新增了多种加密方式,也改变了密码的格式。

    要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密,spring security 官方推荐的是使用bcrypt加密方式。那么如何对密码加密呢,只需要在configure方法里面指定一下。

    修改后是这样的:

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //inMemoryAuthentication 从内存中获取 
    auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("user1").password(new BCryptPasswordEncoder().encode("123456")).roles("USER");
    }


    在inMemoryAuthentication()后面多了".passwordEncoder(new BCryptPasswordEncoder())",这相当于登陆时用BCrypt加密方式对用户密码进行处理。以前的".password("123456")" 变成了 ".password(new BCryptPasswordEncoder().encode("123456"))" ,这相当于对内存中的密码进行Bcrypt编码加密。比对时一致,说明密码正确,允许登陆。

    如果你现在用的也是从内存中取密码,那么按照上面这么修改后应该会成功登录没有问题的。

    如果你用的是在数据库中存储用户名和密码,那么一般是要在用户注册时就使用BCrypt编码将用户密码加密处理后存储在数据库中。并且修改configure()方法,加入".passwordEncoder(new BCryptPasswordEncoder())",保证用户登录时使用bcrypt对密码进行处理再与数据库中的密码比对。如下:

    //注入userDetailsService的实现类
    auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
  • 相关阅读:
    e621. Activating a Keystroke When Any Child Component Has Focus
    e587. Filling Basic Shapes
    e591. Drawing Simple Text
    e595. Drawing an Image
    e586. Drawing Simple Shapes
    e636. Listening to All Key Events Before Delivery to Focused Component
    在 PL/SQL 块的哪部分可以对初始变量赋予新值? (选择1项)
    Oracle数据库中,在SQL语句中连接字符串的方法是哪个?(选择1项)
    你判断下面语句,有什么作用?(单选)
    Oracle数据库表空间与数据文件的关系描述正确的是( )
  • 原文地址:https://www.cnblogs.com/lywJ/p/10984827.html
Copyright © 2011-2022 走看看