一.新建项目

  1.首先新建一个 Spring Boot 项目,创建时引入 Spring Security 依赖和 web 依赖,如下图:

    

 

 

  2.项目创建成功后,Spring Security 的依赖就添加进来了,在 Spring Boot 中我们加入的是 spring-boot-starter-security

 

       我们添加一个测试的 HelloController,内容如下:

  

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

 

  3.我们直接来启动项目,在项目启动过程中,我们会看到一行日志:Using generated security password:一串uuid的数字----------这就是为默认用户user生成的  密码

 

  4.接下来我们去访问 http://localhost:8080/hello 接口,就可以看到自动重定向到登录页面了:

    

 

 

   5.登录时,默认的用户名就是 user,默认的登录密码则是项目启动时控制台打印出来的密码,输入用户名密码之后,就登录成功了,登录成功后,我们就可以访问到 /hello 接口了。

      【注】在 Spring Security 中,默认的登录页面和登录接口,都是 /login ,只不过一个是 get 请求(登录页面:即登录时看到的页面),另一个是 post 请求(登录接口:即登录页面被提交

                                                        的路径)。

      【注】用户相关的自动化配置类在 UserDetailsServiceAutoConfiguration 里边

 

二.不使用数据库怎么自定义用户名密码?

  1.application.properties配置

spring.security.user.name=用户名
spring.security.user.password=密码

  2.配置类中配置用户名/密码。

    (1)首先我们自定义 MySecurityConfig 继承自 WebSecurityConfigurerAdapter,重写里边的 configure (AuthenticationManagerBuilder auth)

方法

      

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("xxx")
                .password("123").roles("admin");
    }
}

    解释:

    1.提供了一个 PasswordEncoder 的实例,因为目前的案例还比较简单,因此暂时先不给密码进行加密,所以返回 NoOpPasswordEncoder 的实例即可。

     2. configure 方法中,我们通过 inMemoryAuthentication 来开启在内存中定义用户,withUser 中是用户名,password 中则是用户密码,roles 中是用户角色。

     3.如果需要配置多个用户,用 and 相连。and 符号相当于就是 XML 标签的结束符,表示结束当前标签,这是个时候上下文会回到 inMemoryAuthentication 方法中,然后开启新用户的配置

 

三.自定义表单登录页

  1.继续完善前面的 MySecurityConfig 类,继续重写它的 configure(WebSecurity web) 和 configure(HttpSecurity http) 方法,如下:

 

  

@Override
public void configure(WebSecurity web) throws Exception {
  //web.ignoring() 用来配置忽略掉的 URL 地址,一般用于静态文件 web.ignoring().antMatchers(
"/js/**", "/css/**"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.html") //登录页面的地址
       .loginProcessingUrl("/loginSecuss") //登录接口的地址,如果不配置,默认和登录页面路径一样,只不过登录页面是get请求,登录接口是post请求 .usernameParameter("name") //可以修改登录页面默认的userName用户名
       .passwordParameter("passwd")
//可以修改登录页面默认的password密码
       .permitAll()
            .and()
            .csrf().disable();
}

 

四.登录成功回调(前后端不分离)

  

  1. defaultSuccessUrl(重载方法)
      1.    一个参数的 defaultSuccessUrl 方法。如果我们在 defaultSuccessUrl 中指定登录成功的跳转页面为 /index,此时分两种情况,如果你是直接在浏览器中输入的登录地址,登录成功后,就直接跳转到 /index,如果你是在浏览器中输入了其他地址,例如 http://localhost:8080/其他页面路径,结果因为没有登录,又重定向到登录页面,此时登录成功后,就不会来到 /index ,而是来到 /其他页面路径 。
      2.          二个参数的 defaultSuccessUrl 方法。如果不设置默认为 false,也就是我们上面的的情况,如果手动设置第二个参数为 true,则 defaultSuccessUrl 的效果和 successForwardUrl 一致。
  2. successForwardUrl
    1.   表示不管你是从哪里来的,登录后一律跳转到 successForwardUrl 指定的地址。例如 successForwardUrl 指定的地址为 /index ,你在浏览器地址栏输入 http://localhost:8080/hello,结果因为没有登录,重定向到登录页面,当你登录成功之后,就会服务端跳转到 /index 页面;或者你直接就在浏览器输入了登录页面地址,登录成功后也是来到 /index

 

 五.登录失败回调(前后端不分离)

  1.failureForwardUrl 是登录失败之后会发生服务端跳转,

  2.failureUrl 则在登录失败之后,会发生重定向。

 

.注销登录

  注销登录的默认接口是 /logout,我们也可以配置

.and()
.logout()
.logoutUrl("/logout")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout","POST"))
.logoutSuccessUrl("/index")
.deleteCookies()
.clearAuthentication(true)
.invalidateHttpSession(true)
.permitAll()
.and()

 

  1. 认注销的 URL 是 /logout,是一个 GET 请求,我们可以通过 logoutUrl 方法来修改默认的注销 URL。
  2. logoutRequestMatcher 方法不仅可以修改注销 URL,还可以修改请求方式,实际项目中,这个方法和 logoutUrl 任意设置一个即可。
  3. logoutSuccessUrl 表示注销成功后要跳转的页面。
  4. deleteCookies 用来清除 cookie。
  5. clearAuthentication 和 invalidateHttpSession 分别表示清除认证信息和使 HttpSession 失效,默认可以不用配置,默认就会清除。

 

七.前后端分离的登录成功和登录失败的回调

  1.登录成功     successHandler

  

.successHandler((req, resp, authentication) -> {
    Object principal = authentication.getPrincipal();
    resp.setContentType("application/json;charset=utf-8");
    PrintWriter out = resp.getWriter();
    out.write(new ObjectMapper().writeValueAsString(principal));
    out.flush();
    out.close();
})

 

    successHandler 方法的参数是一个 AuthenticationSuccessHandler 对象,这个对象中我们要实现的方法是 onAuthenticationSuccess。

    onAuthenticationSuccess 方法有三个参数,分别是:

        1.HttpServletRequest      //可以做服务端跳转

        2.HttpServletResponse     //可以做客户端跳转

        3.Authentication       //保存了我们刚刚登录成功的用户信息

  2.登录失败    failureHandler

 

  

.failureHandler((req, resp, e) -> {
    resp.setContentType("application/json;charset=utf-8");
    PrintWriter out = resp.getWriter();
    out.write(e.getMessage());
    out.flush();
    out.close();
})

 

    第一第二个参数和登录成功的参数一样,第三个是一个 Exception,对于登录失败,会有不同的原因,Exception 中则保存了登录失败的原因

 

 

八 注销登录 (前后端分离

.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler((req, resp, authentication) -> {
    resp.setContentType("application/json;charset=utf-8");
    PrintWriter out = resp.getWriter();
    out.write("注销成功");
    out.flush();
    out.close();
})
.permitAll()
.and()

 

前后端分离  之后,返回的是json

 

posted on 2020-04-26 13:34  印记XP  阅读(163)  评论(0编辑  收藏  举报