Spring Boot笔记-Spring Boot与安全(十三)

1.安全

常见的安全框架有Spring Security,Shiro。它们用来做身份认证,权限控制,预防攻击等。

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

Spring Security的两个目标就是“认证”和“授权”。

认证(Authentication):简单点说就是,你是谁。

授权(Authorization):简单点说就是,你能做什么。

新建Spring Boot项目,引入Spring Web,Thymeleaf,Spring Security依赖。在template文件夹下,加入一些html页面,编写一个Controller处理请求。

package com.atguigu.security.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Controller
public class KungfuController {
    private final String PREFIX = "pages/";

    // 欢迎页
    @GetMapping("/")
    public String index() {
        return "welcome";
    }

    // 登录页
    @GetMapping("/userlogin")
    public String loginPage() {
        return PREFIX+"login";
    }

    // level1页面映射
    @GetMapping("/level1/{path}")
    public String level1(@PathVariable("path")String path) {
        return PREFIX+"level1/"+path;
    }

    // level2页面映射
    @GetMapping("/level2/{path}")
    public String level2(@PathVariable("path")String path) {
        return PREFIX+"level2/"+path;
    }

    // level3页面映射
    @GetMapping("/level3/{path}")
    public String level3(@PathVariable("path")String path) {
        return PREFIX+"level3/"+path;
    }
}

2.Web&安全

要想Spring Security生效,需要在写一个安全配置类,继承WebSecurityConfigurerAdapter,并在类上加@EnableWebSecurity注解。在配置类里实现两个方法,定义认证规则和授权规则。

package com.atguigu.security.config;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    // 定义授权规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 请求路径是/的,允许访问
        // 请求路径是/level1开头的,允许角色是VIP1的访问
        // 请求路径是/level2开头的,允许角色是VIP2的访问
        // 请求路径是/level3开头的,允许角色是VIP3的访问
        http.authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("VIP1")
                .antMatchers("/level2/**").hasRole("VIP2")
                .antMatchers("/level3/**").hasRole("VIP3");
        // 开启自动配置的登陆功能,会自动生成一个登录页,,默认情况下,对应的是/login请求
        // 如果认证失败,会重定向到/login?error
        // 如果需要自定义请求,使用loginPage()方法指定
        // 在自定义页面,需要发送/userlogin请求实现登陆,action要指向/userlogin
        // 其中get是访问登录页,post是提交表单进行登录
        // 自定义页面上,默认的两个input对应name是username和password
        // 如果页面上想使用usr和pwd作为name,在这里告诉http,也就是usernameParameter("usr")和passwordParameter("pwd")
        http.formLogin().loginPage("/userlogin").usernameParameter("usr").passwordParameter("pwd");
        // 开启自动配置的注销功能,会访问一个/logout请求,清空session
        // 默认情况下,注销成功后,返回/login?logout,可以通过logoutSuccessUrl()方法来指定
        http.logout().logoutSuccessUrl("/");
        // 开启记住我功能
        // 勾选了“记住我”之后,会保存一个remember-me的cookie,默认14天过期
        // 点击注销,会删除这个cookie
        // 通过rememberMeParameter("remember")指定自定义页面记住我input对应的name
        http.rememberMe().rememberMeParameter("remember");
    }

    // 定义认证规则
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // Spring Boot 2.x的密码必须是密文,指定密码加密方式是BCryptPasswordEncoder方式,传入的密码是经过BCryptPasswordEncoder处理的
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP1", "VIP2").and()
                .withUser("lisi").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP2", "VIP3").and()
                .withUser("wangwu").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP3", "VIP1");
    }
}

再次访问页面,发送/level1或/level2或/level3路径的请求时,会先检查有没有登陆,如果没有登录,会跳转到登陆,如果登陆了,对用户的role进行验证, 看他有没有权限访问。

为了让页面显示更加灵活,未登录时候不显示内容,不同role登陆之后,只显示这个role能看到的内容。在pom.xml里加入一个依赖。

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>

修改welcome.html的页面代码,引入sec的命名空间,通过sec的属性控制显示的内容,使其根据登陆状态灵活显示。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>
<h1 align="center">欢迎光临武林秘籍管理系统</h1>
<div sec:authorize="!isAuthenticated()">
    <h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/userlogin}">请登录</a></h2>
</div>
<div sec:authorize="isAuthenticated()">
    <h2>
        <span sec:authentication="name"></span>,您好,您的角色有:<span sec:authentication="principal.authorities"></span>
    </h2>
    <form th:action="@{/logout}" method="post">
        <input type="submit" value="注销"/>
    </form>
</div>
<hr>
<div sec:authorize="hasRole('VIP1')">
    <h3>普通武功秘籍</h3>
    <ul>
        <li><a th:href="@{/level1/1}">罗汉拳</a></li>
        <li><a th:href="@{/level1/2}">武当长拳</a></li>
        <li><a th:href="@{/level1/3}">全真剑法</a></li>
    </ul>
</div>
<div sec:authorize="hasRole('VIP2')">
    <h3>高级武功秘籍</h3>
    <ul>
        <li><a th:href="@{/level2/1}">太极拳</a></li>
        <li><a th:href="@{/level2/2}">七伤拳</a></li>
        <li><a th:href="@{/level2/3}">梯云纵</a></li>
    </ul>
</div>
<div sec:authorize="hasRole('VIP3')">
    <h3>绝世武功秘籍</h3>
    <ul>
        <li><a th:href="@{/level3/1}">葵花宝典</a></li>
        <li><a th:href="@{/level3/2}">龟派气功</a></li>
        <li><a th:href="@{/level3/3}">独孤九剑</a></li>
    </ul>
</div>
</body>
</html>

因为要跳转到自定义的login页面,这里把自定义的login.html贴一下。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>
<body>
<h1 align="center">欢迎登陆武林秘籍管理系统</h1>
<hr>
<div align="center">
    <form th:action="@{/userlogin}" method="post">
        用户名:<input name="usr"/><br>
        密码:<input name="pwd"><br/>
        <input type="checkbox" name="remember">记住我<br/>
        <input type="submit" value="登陆">
    </form>
</div>
</body>
</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值