【SpringBoot】SpringSecurity 快速入门

一、简介

Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于 Spring 的应用程序的事实上的标准。

Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架。与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。

Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术类型,它可以实现强大的Web安全控制。对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置即可实现强大的安全跨管理。


有几个重要的类需要记住:

WebSecurityConfigurationAdapter:自定义Security策略(Web安全配置适配器)。

AuthenticationManagerBuilderr:自定义认证策略(身份验证管理器生成器)。

@EnableWebSecurity:开启WebSecurity模式(启用Web安全注解)。

spring Security的两个主要目标是“认证”(Authentication)和“授权/访问控制”(Authorization)。这个概念四通用的,而不是在Spring Security中特有的。

参考文档1:https://docs.spring.io/spring-security/site/docs/current/reference/html5/

参考文档2:https://docs.spring.io/springsecurity/site/docs/5.2.0.RELEASE/reference/htmlsingle/



二、使用SpringSecurity

在这里插入图片描述

注意:thymeleaf最高支持的springboot的版本为2.0.9,我们使用的是2.0.7版本的springboot,如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.7.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

1、导入依赖

security启动器依赖:springsecurity和thymeleaf可以集合使用

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

springsecurity-thymeleaf依赖

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
    <version>3.0.4.RELEASE</version>
</dependency>

2、基础环境搭建

需要的前端文件以及目录结构:
在这里插入图片描述
介绍一些indexPage.html中的一些特别之处。因为thymeleaf是可以与springsecurity进行交互的,可以实现一些个性化的设置,比如:如果登录了显示登录人的名字和注销按钮,如果没登录显示登录按钮。

xmlns:th=“http://www.thymeleaf.org”:thymeleaf标签

xmlns:sec=“http://www.thymeleaf.org/thymeleaf-extras-springsecurity4”:thymeleaf-springsecurity标签

sec:authorize:授权

isAuthenticated():判断是否已经认证

sec:authentication:认证

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
                xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
    <meta charset="UTF-8">
    <title>index page</title>
</head>
<body>
<div class="box">
    <h2>【主页】 &nbsp;&nbsp;&nbsp;&nbsp;
    	<!--判断是否登录,!isAuthenticated()为true则生效<span>-->
        <span sec:authorize="!isAuthenticated()">
            <a th:href="@{/login}">登录</a>
        </span>
		<!--判断是否登录,!isAuthenticated()为true则生效<span>-->
        <span sec:authorize="isAuthenticated()">
            用户名:<span sec:authentication="name"></span>&nbsp;&nbsp;&nbsp;&nbsp;
            <a th:href="@{/logout}">注销</a>
        </span>
    </h2>
    <br><br>
    <a th:href="@{/admin}">进入管理员页面</a>
    <br><br>
    <a th:href="@{/user}">进入用户页面</a>
    <br><br>
    <a th:href="@{/tourist}">进入游客页面</a>
</div>
</body>
</html>

编写路由控制器类:

package com.tiger.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class routeController {

    @RequestMapping("/admin")
    public String admin(){
        return "pages/admin/adminPage";
    }

    @RequestMapping("/user")
    public String user(){
        return "pages/user/userPage";
    }

    @RequestMapping("/tourist")
    public String tourist(){
        return "pages/tourist/touristPage";
    }

    @RequestMapping("/login")
    public String login(){
        return "pages/loginPage";
    }
}


3、编写SecurityConfig配置类

基本结构:

package com.tiger.config;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;


@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	.......
}


①、重写configure(HttpSecurity http)方法

重写configure(HttpSecurity http)实现页面角色设置:

对于不同的页面,我们可能会有不同的权限,怎么给不同的页面设置不同的权限,在原生的Javaweb中,我们可能会用到过滤器(filter),但是在SpringSecurity中,我们只需要继承一个类就可以。

authorizeRequests():授权请求

antMatchers(String str):设置匹配url

hasRole(String str):设置角色

permitAll():允许所有的角色通过

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            //设置页面角色(匹配器)
            .antMatchers("/").permitAll()
            .antMatchers("/admin/**").hasRole("admin")
            .antMatchers("/user/**").hasRole("user")
            .antMatchers("/tourist/**").hasRole("tourist");
}

重写configure(HttpSecurity http)实现登录与注销:

在SpringSecurity中实现登录与注销,变得异常的简单,不用在通过原本的javaweb进行繁琐的检验与判断。

formLogin():表单登录

loginPage("/login"):设置用于登录使用的页面

passwordParameter(“username”):接收表单中name=username的参数

passwordParameter(“password”):接收表单中name=password的参数

logoutSuccessUrl(String str):注销成功后的路径设置

@Override
protected void configure(HttpSecurity http) throws Exception {
	//设置登录页面与专递的参数名
    http.formLogin()
        .loginPage("/login")
        .passwordParameter("username")
        .passwordParameter("password");
        
        //设置注销
        .and()
        .logout().logoutSuccessUrl("/")

}

对于注销,有一个固定的访问路径<a th:href="@{/logout}">注销</a>


重写configure(HttpSecurity http)实现无权限的访问的重定向:

对于没有访问权限的用户访问了高权限的url。SpringSecurity会默认跳到一个错误提示页面,体验不好。通常我们都会让其跳到登录页面或者在当前页保持不变。

exceptionHandling():异常处理

accessDeniedPage(String str):访问拒接页面设置

@Override
    protected void configure(HttpSecurity http) throws Exception {
		//设置无权限的访问的默认访问路径
        http.exceptionHandling().accessDeniedPage("/login");
        
    }

重写configure(HttpSecurity http)实现登录时的"记住我":

我们在登录一些比较用心的网站的时候,在我们登录的时候,存在一个"记住我"的单选按钮,当我们勾选之后,即使我们关闭浏览器之后,我们依然可以免登陆访问。其实背后的后继也是很简单的,无非即使session或cookie的应用,只不过在SpringSecurity变得更加的简单了。

rememberMeParameter(String str):str的值要与checkbox的name值相对应,例如:<input type="checkbox" name="rememberMe" value="rememberMe">记住我 <br>

@Override
    protected void configure(HttpSecurity http) throws Exception {
		//设置“记住我”
        http.and()
            .rememberMe().rememberMeParameter("rememberMe");

    }

重写configure(HttpSecurity http)设置csrf禁用

注销按钮要是点击时失败,那么说明你用的是< a>标签,< a>标签使用的是get请求。SpringSecurity中有csrf保护,csrf又称跨域请求伪造,攻击方通过伪造用户请求(get)访问受信任站点

所以我们可以通过表单的post请求实现注销,或者禁用SpringSecurity的csrf保护

@Override
    protected void configure(HttpSecurity http) throws Exception {
		//设置csrf禁用
         http.csrf().disable();

    }

整合上述功能:

@Override
protected void configure(HttpSecurity http) throws Exception {
   http.authorizeRequests()
           //设置页面角色
           .antMatchers("/").permitAll()
           .antMatchers("/admin/**").hasRole("admin")
           .antMatchers("/user/**").hasRole("user")
           .antMatchers("/tourist/**").hasRole("tourist")

           //设置登录页面与专递的参数名
           .and()
           .formLogin()
           .loginPage("/login")
           .passwordParameter("username")
           .passwordParameter("password")

           //设置无权限访问页面的默认路径
           .and()
           .exceptionHandling().accessDeniedPage("/login")


           //设置"记住我"
           .and()
           .rememberMe().rememberMeParameter("rememberMe")

           //设置注销
           .and()
           .logout().logoutSuccessUrl("/")

           //设置csrf禁用
           .and()
           .csrf().disable();

}

②、重写configure(AuthenticationManagerBuilder auth)方法

既然我们前面说了,每个页面都有对应的角色去访问,我们接下来就是给登录见证成功的用户分配角色。

重写configure(AuthenticationManagerBuilder auth)方法校验登录名与密码以及角色(权限)设置。

inMemoryAuthentication():在内存中校验

passwordEncoder(new BCryptPasswordEncoder()):密码编码,一种加密方式

//设置用户名和密码以及对应的角色
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
            .withUser("admin").password(new BCryptPasswordEncoder().encode("admin")).roles("admin","user","tourist")
            .and()
            .withUser("user").password(new BCryptPasswordEncoder().encode("user")).roles("user","tourist")
            .and()
            .withUser("tourist").password(new BCryptPasswordEncoder().encode("tourist")).roles("tourist");
}

您可以找到支持基于 JDBC 的身份验证的更新。下面的示例假设您已经DataSource在应用程序中定义了 a 。该JDBC-javaconfig样品提供了使用基于JDBC认证的一个完整的示例。

@Autowired
private DataSource dataSource;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    // ensure the passwords are encoded properly
    UserBuilder users = User.withDefaultPasswordEncoder();
    auth
        .jdbcAuthentication()
            .dataSource(dataSource)
            .withDefaultSchema()
            .withUser(users.username("user").password("password").roles("USER"))
            .withUser(users.username("admin").password("password").roles("USER","ADMIN"));
}

未完待续…



天下无难事,只怕有心人。天下无易事,只怕粗心人…
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值