SpringBoot学习之路---简单记录整合SpringSecurity实现登录认证授权

基本上每一个项目都会有用户登录的这个功能,用户需要在登录之后才能够去访问一些资源,如果没登录的话就不能访问(403)。我们可以自己编码去实现这样的业务逻辑,当然每一次都自己去编码是比较耗时的,毕竟市面上已经有现成的开源的框架可以拿来使用了(Apache的shiro与Spring的Spring Security),这一篇的博客的主角就是介绍一下后者在SpringBoot中的整合配置,以及如何基本使用


首先还是一样,要用到什么技术,就引入什么技术的maven依赖:

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

同时因为后面还要用到thymeleaf模版引擎,所以我们顺便把thymeleaf也导入了:

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

shiro、Springsecurity这些框架技术都统称为安全框架,安全框架有两个重要的作用,是认证授权。认证是程序确认你是什么身份,而授权就是程序根据你的身份给你不同的权利。

这里不讲空话,用我看的学习资源里面的一个场景,一个武林秘籍系统,用户可以根据不同的权限从而查看到不同的武林秘籍,这是初始的样子:
在这里插入图片描述
我们现在需要做的是点进去每个秘籍,需要不同的身份,比如我是普通的用户,那么我只能去查看普通的武林秘籍,同理,另外两个也是一样,而且,当我们登录之后会去显示出用户的信息和所拥有的身份。

这时就可以用到springsecurity了,我们需要创建一个SpringSecurity的配置类,让其继承于WebSecurityConfigurerAdapter,并实现一些方法:

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@EnableWebSecurity注解的作用是开启security的服务(有点废话),它内部也是个组合注解,有一个@Configuration,可以理解为通知SpringBoot让其扫描到该类。

之后看看让其继承两个方法,为什么是两个呢,一个是认证,另外一个是授权啦:

//授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("VIP1") //普通武林秘籍,并设置所需身份为VIP1
                .antMatchers("/level2/**").hasRole("VIP2") //高级武功秘籍,并设置所需身份为VIP2
                .antMatchers("/level3/**").hasRole("VIP3"); //爵士武功秘籍,并设置所需身份为VIP3

        //自动配置登录,使用这行代码之后,springsecurity会帮我们生成一个登录,并自动帮我们校验用户名和密码!,默认的路径为/login
        http.formLogin();

        //自动配置注销,可以通过访问路径/logout,来帮我们注销当前用户,底层原理是撤销相关的session
        http.logout().logoutSuccessUrl("/");

        //自动配置记住我功能,就像是很多网站的"记住我"功能,使用这个后,下次进入网站无需登录,底层原理是像浏览器发送一个cookie信息,内容是一个sessionid,有效期14天,这样下次访问时带上这个sessionid就能找到session了
        http.rememberMe();
    }

    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    			//这里为了简便,就不从数据库中换取数据了,从内存中获取,inMemoryAuthentication()就是从内存中获取,这里分别设置了两个用户,它们的身份分别是"VIP1""VIP2""VIP3",用户名和密码见具体方法。
                auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("leslie").password("123").roles("VIP1","VIP2")
                .and()
                .withUser("lion").password("123").roles("VIP3");
    }

每一行代码的作用写在注释中。总结下,到这一步,我们做完的事情有给leslielion的两个用户授权VIP1、VIP2和VIP3的身份,并为不同的访问路径授权了不同的用户。

配置类写完之后,还不够,这里controller代码略过了,无非就是控制页面跳转到哪里。前端页面代码也是需要修改了,修改之前需要引入thymeleaf-springsecurity的整合:

<!--        引入thymeleaf与spring security整合-->
        <!-- https://mvnrepository.com/artifact/org.thymeleaf.extras/thymeleaf-extras-springsecurity5 -->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>

修改后的前端代码:

<!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="@{/login}">请登录</a></h2>
</div>


<div sec:authorize="isAuthenticated()">
	<h2 align="center"><span sec:authentication="name"></span>您好,你的角色是:<span sec:authentication="principal.authorities"></span></h2>
	<form method="post" th:action="@{/logout}">
	<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>

这里说明一下,添加一些代码的作用

页面首先需要引入thymeleaf的约束空间:

xmlns:sec="http://www.thymeleaf.org/extras/spring-security"

引入之后就可以使用一些和springsecurity有关的标签了。

  • sec:authentication=“name”:表示取出当前登录的用户名。
  • sec:authentication=“principal.authorities”:取出当前用户的所有身份
  • sec:authorize=“isAuthenticated()”:判断当前状态是否登录,同理属性内前面加一个!表示判断是否未登录,有这个之后,我们以后就不需要自己编写拦截器判断判断登录状态了。
  • sec:authorize=“hasRole(‘VIP3’)”:判断当前登录用户是否有该身份。

之后我们再次查看该页面:

在这里插入图片描述

可以看到 sec:authorize=“isAuthenticated()” 的作用出来了,如果未登录的话,只显示这个,点击登录,看看Springsecurity为我们生成的登录页面:
在这里插入图片描述
还挺好看的,下面的那个单选框"Remember me on this computer"是之前http.rememberMe();所自动配置的功能。首先登录leslie,看看能否显示前两个级别的武功秘籍:

在这里插入图片描述
成功,点击注销(刚刚http.logout()的作用),再换成lion用户试试,看看能否显示绝世武功秘籍:

在这里插入图片描述
简单记录到这里,由于springsecurity的具体知识我也还没有学过,觉得挺方便的,之后找机会补完这方面的知识,再着重记录。

猜你喜欢

转载自blog.csdn.net/Jokeronee/article/details/105948487