Spring Security系列之极速入门与实践教程

@css

1. Spring Security

Spring Security 是 Spring 家族中的一个安全管理框架,应用程序的两个主要区域是“认证”和“受权”(或者访问控制)。Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型html

这两个主要区域是Spring Security 的两个目标。html5

  • “认证”(Authentication),是创建一个他声明的主体的过程(一
    个“主体”通常是指用户,设备或一些能够在你的应用程序中执行动
    做的其余系统)。
  • “受权”(Authorization)指肯定一个主体是否容许在你的应用程序
    执行一个动做的过程。为了抵达须要受权的店,主体的身份已经有认
    证过程创建。

2. 实验环境准备

环境准备:java

  • JDK 1.8
  • SpringBoot2.2.1
  • Maven 3.2+
  • 开发工具
    • IntelliJ IDEA
    • smartGit

建立一个SpringBoot Initialize项目,详情能够参考我以前博客:SpringBoot系列之快速建立项目教程git

在这里插入图片描述
新建项目后,检查一下spring-boot-starter-security场景启动器是否配置成功,不须要写版本github

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

SpringBoot有版本仲裁机制,SpringBoot2.2.1的spring-boot-starter-security依赖的Spring security版本是5.2.1的
在这里插入图片描述web

3. 日志级别修改

配置Spring Security日志级别,默认是info的,能够修改成debugspring

## logback配置
logging:
  level:
    org:
      springframework:
        security: info

4. 配置用户名/密码

随便写个接口,访问时候,就会跳到以下图的登陆页面,为何?咱们只是引入maven配置而已,而后帐号密码是什么?其实这个是Spring Security的默认登陆页面,页面代码是在jar包里的,默认的username是user,密码是随机生成的uuid格式的密码
在这里插入图片描述
密码会在控制台打印,根据线索,找到自动配置类
在这里插入图片描述
要修改默认密码,能够新建application.yml配置文件,加上以下配置数据库

## spring security配置
spring:
  security:
    user:
      name: nicky
      password: 123

也能够新建Spring Security配置类,注意Spring Security5.2.1版本,配置密码要用BCryptPasswordEncoder加密,不过登陆仍是明文,Spring Security不一样版本各有差异,详情配置仍是参考官方文档bootstrap

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {    //auth.inMemoryAuthentication()
        auth.inMemoryAuthentication()
                .withUser("nicky")
                .password(bcryptPasswordEncoder().encode("123"))
                .roles("admin");
    }
	
	@Bean
    public PasswordEncoder bcryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
加密方式 security 4 security 5
bcrypt password {bcrypt}password
ldap password {ldap}password
MD4 password {MD4}password
MD5 password {MD5}password
noop password {noop}password
pbkdf2 password {pbkdf2}password
scrypt password {scrypt}password
SHA-1 password {SHA-1}password
SHA-256 password {SHA-256}password
sha256 password {sha256}password

5. 数据库方式校验

拓展:若是要数据库方式校验用户名密码,能够自定义UserDetailsService方式:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {   
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new CustomPasswordEncoder());
        auth.parentAuthenticationManager(authenticationManagerBean());

    }

UserDetailsServiceImpl.java

package com.example.springboot.oauth2.service;

import com.example.springboot.oauth2.entity.User;
import com.example.springboot.oauth2.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * <pre>
 *
 * </pre>
 *
 * <pre>
 * @author mazq
 * 修改记录
 *    修改后版本:     修改人:  修改日期: 2020/04/30 15:15  修改内容:
 * </pre>
 */
@Slf4j
@Service("userService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    UserMapper userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if(user == null){
            log.info("登陆用户[{}]没注册!",username);
            throw new UsernameNotFoundException("登陆用户["+username + "]没注册!");
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthority());
    }

    private List getAuthority() {
        return Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"));
//        return Arrays.asList(Collections.emptyList());
    }
}
@Override
    protected void configure(HttpSecurity http) throws Exception {
        http   // 配置登陆页并容许访问
                .formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login").permitAll()
                // 配置Basic登陆
                //.and().httpBasic()
                // 配置登出页面
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
                // 开放接口访问权限,不须要登陆受权就能够访问
                .and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**").permitAll()
                // api接口须要admin管理员才能访问
                .antMatchers("/api/**").hasRole("admin")
                // 其他全部请求所有须要鉴权认证
                .anyRequest().authenticated()
                // 关闭跨域保护;
                .and().csrf().disable();
    }

6. 不拦截静态资源

配置文件,加上配置

@Override
    public void configure(WebSecurity web) throws Exception {
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers("/asserts/**");
        web.ignoring().antMatchers("/favicon.ico");
    }

7. 自定义登陆页面

引入Thymeleaf模板引擎:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

关闭Thymeleaf模板引擎缓存,方便F9自动编译

spring:
  thymeleaf:
    cache: false

写个login接口,注意必定要GET方式,POST方式是Spring Security默认的校验接口,接口名称也是/login

@Controller
public class LoginController {

    @GetMapping(value = {"/login"})
    public ModelAndView toLogin() {
        return new ModelAndView("login");
    }
}

自定义登陆页面,要用post方式,除非你本身写个校验接口,POST /login是Spring Security官方的校验接口,默认用户名参数为username,密码参数为password:

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
		<meta name="description" content="" />
		<meta name="author" content="" />
		<title>Signin Template for Bootstrap</title>
		<!-- Bootstrap core CSS -->
		<link href="../static/asserts/css/bootstrap.min.css" th:href="@{asserts/css/bootstrap.min.css}" rel="stylesheet" />
		<!-- Custom styles for this template -->
		<link href="../static/asserts/css/signin.css" th:href="@{asserts/css/signin.css}" rel="stylesheet"/>
	</head>

	<body class="text-center">
		<form class="form-signin" th:action="@{/login}" method="post">
			<img class="mb-4" th:src="@{asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72" />
			<h1 class="h3 mb-3 font-weight-normal" >Oauth2.0 Login</h1>
			<label class="sr-only" >Username</label>
			<input type="text" class="form-control" name="username" required="" autofocus="" value="nicky" />
			<label class="sr-only" >Password</label>
			<input type="password" class="form-control" name="password" required="" value="123" />
			<div class="checkbox mb-3">
				<label>
          <input type="checkbox" value="remember-me"  /> remember me
        </label>
			</div>
			<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
			<p class="mt-5 mb-3 text-muted">© 2019</p>
		</form>

	</body>

</html>

修改配置文件,.loginPage("/login")指定自定义的登陆页面

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http   // 配置登陆页并容许访问
                .formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login").permitAll()
                // 配置Basic登陆
                //.and().httpBasic()
                // 配置登出页面
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
                // 开放接口访问权限,不须要登陆受权就能够访问
                .and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**").permitAll()
                // api接口须要admin管理员才能访问
                .antMatchers("/api/**").hasRole("admin")
                // 其他全部请求所有须要鉴权认证
                .anyRequest().authenticated()
                // 关闭跨域保护;
                .and().csrf().disable();
    }

在这里插入图片描述

8. Remember me

开启记住我功能,登录成功之后,将cookie发给浏览器保存,之后访问页面带上这个cookie,只要经过检查就能够免登陆

@Override
    protected void configure(HttpSecurity http) throws Exception {
      //开启记住我功能,登录成功之后,将cookie发给浏览器保存,之后访问页面带上这个cookie,只要经过检查就能够免登陆
        http.rememberMe().rememberMeParameter("remeber");

    }

ok,Spring Security的知识点比较多,详情请参考官方文档,本博客参考官方文档,作了简单记录,仅仅做为入门参考手册

代码例子下载:code download

相关文章
相关标签/搜索