Spring Security入门教程 通俗易懂 超详细 【内含案例】

By | 2020年7月31日

Spring Security的简单使用

推荐 Java 常见面试题

简介

  • SSM 整合 Security 是比较麻烦的,虽然Security的功能比 Shiro 强大,相反却没有Shiro的使用量多
  • SpringBoot出现后简化了Spring系列的配置文件,因此SpringSecurity的使用逐渐增加

一、创建项目

查看代码

在 SpringBoot 中直接引入 Spring Security 依赖即可

image

创建项目的启动类

image

创建 SecurityController 类

image

  • 启动后访问 localhost:8080/hello
  • 会自动跳到 localhost:8080/login
  • 需要登录后才能访问 /hello

image

二、用户名配置

查看代码

  • 默认情况下用户名是 user ,而密码会在项目启动时 控制台 打印出一串随机 字符串,这就是密码.每次启动项目,密码都不一样

image

  • 对登录的用户名/密码进行配置,有三种不同的方式
  1. application 配置文件中声明
  2. java 代码配置在内存里
  3. 通过获取 数据库

第一种方式 application.yml 文件中

image

第二种方式 创建一个SecurityConfig配置类,继承 WebSecurityConfigurerAdapter

image

第三种方法没有进行演示,就是在数据库中取出usernamepassword配置到内存中

三、忽略拦截

查看代码

image

在配置类中重写 configure(WebSecurity web) 方法,然后直接访问即可

image

pom.xml文件

返回阅读

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--Web项目 需引入web依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
启动类文件
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author https://www.cnblogs.com/beixuan/
 */
@SpringBootApplication
public class SecurityApplication {
    public static void main(String[] args) {
        SpringApplication.run(SecurityApplication.class, args);
    }
}
SecurityController 文件
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author https://www.cnblogs.com/beixuan/
 */
@RestController
public class SecurityController {

    /**
     * 不用登录就可访问
     * @return
     */
    @RequestMapping("/hi")
    public String sayHi(){
        return "Hi bro!";
    }

    @RequestMapping("/hello")
    public String sayHello(){
        return "Hello bro!";
    }
}
application.yml 配置文件

返回阅读

spring:
  security:
    user:
      name: beixuan
      password: beixuan
SecurityConfig Java配置文件

此方法配置用户与配置 yml 文件效果一致

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author https://www.cnblogs.com/beixuan/
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        //Spring Security5之后 官方需要密码强制加密,如不想加密可创建一个过期的 PasswordEncoder 的实例 NoOpPasswordEncoder,但不安全
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String password = bCryptPasswordEncoder.encode("beixuan");
        //添加一个用户[beixuan] 角色为[admin] 密码是[beixuan加密后的密钥]
        auth.inMemoryAuthentication()
                .withUser("beixuan")
                .roles("admin")
                .password(password);
    }

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
  • 具体的登录配置 下面代码借鉴于 江南一点雨 随笔的代码,有兴趣可以看看
  • VerifyCodeFilter 一次性验证码,可以查看资料了解其使用方法,这里不再叙述
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    VerifyCodeFilter verifyCodeFilter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);
        http
        .authorizeRequests()//开启登录配置
        .antMatchers("/hello").hasRole("admin")//表示访问 /hello 这个接口,需要具备 admin 这个角色
        .anyRequest().authenticated()//表示剩余的其他接口,登录之后就能访问
        .and()
        .formLogin()
        //定义登录页面,未登录时,访问一个需要登录之后才能访问的接口,会自动跳转到该页面
        .loginPage("/login_p")
        //登录处理接口
        .loginProcessingUrl("/doLogin")
        //定义登录时,用户名的 key,默认为 username
        .usernameParameter("uname")
        //定义登录时,用户密码的 key,默认为 password
        .passwordParameter("passwd")
        //登录成功的处理器
        .successHandler(new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("success");
                    out.flush();
                }
            })
            .failureHandler(new AuthenticationFailureHandler() {
                @Override
                public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("fail");
                    out.flush();
                }
            })
            .permitAll()//和表单登录相关的接口统统都直接通过
            .and()
            .logout()
            .logoutUrl("/logout")
            .logoutSuccessHandler(new LogoutSuccessHandler() {
                @Override
                public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write("logout success");
                    out.flush();
                }
            })
            .permitAll()
            .and()
            .httpBasic()
            .and()
            .csrf().disable();
    }
忽略拦截分两步

返回阅读

增加访问路径/hi

/**
 * 不用登录就可访问
 * @return
 */
@RequestMapping("/hi")
public String sayHi(){
    return "Hi bro!";
}

增加配置代码

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/hi");
}

即可不用登录访问/hi路径

END

本文就先说到这里,有问题欢迎留言讨论

Category: 未分类

发表评论

电子邮件地址不会被公开。 必填项已用*标注