• 基本准备
    • 基础页面
    • 基础数据库
    • 页面访问的控制类
  • 自定义用户身份认证
    • JDBC身份认证
  • 自定义用户授权管理
    • 自定义用户访问控制
    • 自定义403页面(访问权限不够时的页面)
    • 自定义登录页面
    • 用户退出登录
    • 获取登录用户信息
      • 使用SecurityContextHolder获取
      • 用Security的sec标签获取
    • 将thymeleaf用在js里面

文件目录结构:

基本准备

基础页面

所有页面均使用的 Bootstrap

我们最后实现的效果是:
一个视频首页、先判断是否登录,没有登录的跳转至登录页面;
登录后,有两种身份:普通用户、VIP用户,每种身份有不同的权限;
登录后可显示用户名且可以退出;

  • 登录页面(login.html)
    登录页面就用我们之前的国际化即可https://blog.csdn.net/weixin_44162239/article/details/115414902

  • 视频首页(index.html)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>首页</title><link href="//cdn.staticfile.org/twitter-bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet"><script type="text/javascript" src="//cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script><script type="text/javascript" src="//cdn.staticfile.org/twitter-bootstrap/3.0.1/js/bootstrap.min.js"></script></head>
<body><div class="container"><div class="row clearfix"><div class="col-md-12 column"><nav class="navbar navbar-default navbar-fixed-top" role="navigation"><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav navbar-right"><li><a th:href="@{/login}">登录</a></li></ul></div></nav><div class="alert alert-danger" style="margin-top: 65px;" th:if="${param.logout}">您已退出登录</div><div class="carousel slide" id="carousel-351237"><ol class="carousel-indicators"><li data-slide-to="0" data-target="#carousel-351237"></li><li data-slide-to="1" data-target="#carousel-351237"></li><li data-slide-to="2" data-target="#carousel-351237" class="active"></li></ol><div class="carousel-inner"><div class="item"><img alt="" th:src="@{/login/images/mt.jpg}" /></div><div class="item"><img alt="" th:src="@{/login/images/xw.jpg}" /></div><div class="item active"><img alt="" th:src="@{/login/images/lx.jpg}" /></div></div> <a class="left carousel-control" href="#carousel-351237" data-slide="prev"><span class="glyphicon glyphicon-chevron-left"></span></a> <a class="right carousel-control" href="#carousel-351237" data-slide="next"><span class="glyphicon glyphicon-chevron-right"></span></a></div></div></div><div class="row clearfix"><div class="col-md-6 column"><h3>向往的生活 第五季</h3><p>《向往的生活》是由湖南卫视推出的大型生活服务纪实节目。节目记录了何炅、黄磊、张艺兴、彭昱畅、张子枫等人一起守拙归园田蘑菇屋,为观众带来一幅“自力更生,自给自足,温情待客,完美生态”的生活画面。</p><a th:href="@{details/common/1}">点击观看</a></div><div class="col-md-6 column"><h3>明星大侦探之名侦探学院 第二季</h3><p>《明星大侦探之名侦探学院 第二季》为《明星大侦探》兄弟篇,节目邀请了颜值与智商兼具的学霸少年进行实景推理“剧本杀”,共度欢乐爆笑的合宿生活,上演高能脑力对决。</p><a th:href="@{details/vip/1}">点击观看</a></div></div>
</div>
</body>
</html>
  • 只vip可看的视频页面(details/vip/1.html)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>vip</title><link href="//cdn.staticfile.org/twitter-bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container"><div class="row clearfix"><div class="col-md-12 column"><div class="row clearfix"><div class="col-md-2 column"><img th:src="@{/login/images/mx.jpg}" /></div><div class="col-md-6 column" style="    margin-left: 93px;"><h3>明星大侦探之名侦探学院 第二季</h3><p class="lead">《明星大侦探之名侦探学院 第二季》为《明星大侦探》兄弟篇,节目邀请了颜值与智商兼具的学霸少年进行实景推理“剧本杀”,共度欢乐爆笑的合宿生活,上演高能脑力对决。</p></div><div class="col-md-4 column"></div></div></div></div>
</div>
</body>
</html>
  • 普通用户可看的视频页面(details/common/1.html)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>common</title><link href="//cdn.staticfile.org/twitter-bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container"><div class="row clearfix"><div class="col-md-12 column"><div class="row clearfix"><div class="col-md-2 column"><img th:src="@{/login/images/bg.jpg}" /></div><div class="col-md-6 column" style="margin-left: 93px;"><h3>向往的生活 第五季</h3><p class="lead">《向往的生活》是由湖南卫视推出的大型生活服务纪实节目。节目记录了何炅、黄磊、张艺兴、彭昱畅、张子枫等人一起守拙归园田蘑菇屋,为观众带来一幅“自力更生,自给自足,温情待客,完美生态”的生活画面。</p></div><div class="col-md-4 column"></div></div></div></div>
</div>
</body>
</html>

基础数据库

  • t_customer(用户表)
    username(用户名必须唯一)、password(密码,必须是加密后的)、valid(用户是否合法,tinyint类型)这三个字段必须存在
  • t_authority(用户权限表)
    authority字段的值必须为ROLE_***
  • t_customer_authority(用户权限关联表)
/*  数据库叫 springboot */SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for t_authority
-- ----------------------------
DROP TABLE IF EXISTS `t_authority`;
CREATE TABLE `t_authority` (`id` int(20) NOT NULL AUTO_INCREMENT,`authority` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of t_authority
-- ----------------------------
INSERT INTO `t_authority` VALUES ('1', 'ROLE_common');
INSERT INTO `t_authority` VALUES ('2', 'ROLE_vip');-- ----------------------------
-- Table structure for t_customer
-- ----------------------------
DROP TABLE IF EXISTS `t_customer`;
CREATE TABLE `t_customer` (`id` int(20) NOT NULL AUTO_INCREMENT,`username` varchar(200) DEFAULT NULL,`password` varchar(200) DEFAULT NULL,`valid` tinyint(1) NOT NULL DEFAULT '1',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of t_customer
-- ----------------------------
INSERT INTO `t_customer` VALUES ('1', 'shitou', '$2a$10$5ooQI8dir8jv0/gCa1Six.GpzAdIPf6pMqdminZ/3ijYzivCyPlfK', '1');
INSERT INTO `t_customer` VALUES ('2', '李四', '$2a$10$5ooQI8dir8jv0/gCa1Six.GpzAdIPf6pMqdminZ/3ijYzivCyPlfK', '1');/*  对应密码均为 123456*/-- ----------------------------
-- Table structure for t_customer_authority
-- ----------------------------
DROP TABLE IF EXISTS `t_customer_authority`;
CREATE TABLE `t_customer_authority` (`id` int(20) NOT NULL AUTO_INCREMENT,`customer_id` int(20) DEFAULT NULL,`authority_id` int(20) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of t_customer_authority
-- ----------------------------
INSERT INTO `t_customer_authority` VALUES ('1', '1', '1');
INSERT INTO `t_customer_authority` VALUES ('2', '2', '2');

页面访问的控制类

package com.zknu.inter.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@Controller
public class MovieController {@GetMapping("/details/{type}/{path}")public String toMovie(@PathVariable("type") String type,@PathVariable("path") String path){return "details/"+type+"/"+path;}// 访问 details下不同权限的页面
}

自定义用户身份认证

身份认证就是判断你输入的用户名和密码是否正确

JDBC身份认证

JDBC认证是用数据库中的信息进行认证

添加依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>

连接数据库配置
和以前一样,不写了
进行身份认证(SecurityConfig)
重写 WebSecurityConfigurerAdapter 中的 configure 方法

package com.zknu.inter.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;import javax.sql.DataSource;@EnableWebSecurity  // 开启MVC Security 安全支持
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate DataSource dataSource;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 对密码进行编码BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();String userSQL = "select name,password,valid from t_customer where name = ?";String authoritySQL = "select c.name,a.authority from t_customer c,t_authority a,t_customer_authority ca " +"where ca.customer_id=c.id and ca.authority_id=a.id and c.name=?";// 两句SQL语句基本固定 ,必须至少返回为这些值auth.jdbcAuthentication().passwordEncoder(encoder).dataSource(dataSource).usersByUsernameQuery(userSQL).authoritiesByUsernameQuery(authoritySQL);}}

此时我们访问 http://localhost:8080
发现会自动跳转至 Security 自带的登录页面

登录成功会进去首页
登录失败会报错

登录成功后发现我们不论哪一种身份都可访问所有页面,所以我们接下来进行用户自定义访问控制,控制页面的访问权限

自定义用户授权管理

自定义用户访问控制

接着重写 configure 方法,两个方法的参数不一样

package com.zknu.inter.config;import org.springframework.beans.factory.annotation.Autowired;
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;import javax.sql.DataSource;@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate DataSource dataSource;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();String userSQL = "select name,password,valid from t_customer where name = ?";String authoritySQL = "select c.name,a.authority from t_customer c,t_authority a,t_customer_authority ca " +"where ca.customer_id=c.id and ca.authority_id=a.id and c.name=?";auth.jdbcAuthentication().passwordEncoder(encoder).dataSource(dataSource).usersByUsernameQuery(userSQL).authoritiesByUsernameQuery(authoritySQL);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()  // 开启请求访问限制.antMatchers("/").permitAll()  // 允许对index页面直接访问.antMatchers("/login/**").permitAll() //  对 /login/ 下的所有文件允许访问(页面的静态资源文件).antMatchers("/details/common/**").hasAnyRole("common","vip")// 允许权限为 common 和 vip 的用户访问 common下的所有文件.antMatchers("/details/vip/**").hasRole("vip")// 仅允许权限为 vip 的用户访问 vip 下的所有文件.anyRequest().authenticated()/*匹配已经登录认证的用户*/.and()  // 功能连接.formLogin();// 开启基于表单的用户登陆}
}

静态资源目录结构

此时我们访问 http://localhost:8080
发现并没有自动跳到登录页面,因为我们对该页面进行了放行。
任意点击一个链接,发现会跳至登录页面,因为当我们请求details下的页面时,发现我们没有登录,所以会被拦截并跳转至登录页面。我们登录shitou的账号密码。
登录成功后会跳到刚刚想要访问的页面

因为shitou 的权限时普通用户,因此我们访问vip页面时会报403错误(无访问权限)

加了权限访问之后,测试会变得很麻烦,因为很多页面会变得没有访问权限,所以之后测试的时候报错首先考虑是否有访问权限。

自定义403页面(访问权限不够时的页面)

但是这个页面时非常不美观的,所以我们可以写一个403页面作为访问权限不够时的提示页面

403.html

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>暂无访问权限</title><link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css"><script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script><script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body><div class="container" style="margin-top: 5%"><div class="jumbotron"><p>开通会员后观看</p><p><a class="btn btn-primary btn-lg" role="button">立即开通</a></p></div>
</div></body>
</html>

403页面访问控制器

@GetMapping("/403")public String authority(){return "403";}

在用户访问控制中加上

.and().exceptionHandling().accessDeniedPage("/403")


就可以在权限不够的时候访问至403页面了。

此时我们再用shitou 用户访问 vip 页面:

发现我们自定义的页面已经取代了原先那个满是提示报错的页面

自定义登录页面

但我们此时的登录页面仍为Security的默认页面,不太合适吧,所以我们自己自定义一个。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>登录</title><link th:href="@{/login/css/bootstrap.min.css}" rel="stylesheet"><link th:href="@{/login/css/login.css}" rel="stylesheet">
</head>
<body><form class="sign" method="post" th:action="@{/login}"><img class="img-circle img" th:src="@{/login/images/hr.jpg}"><h2 th:text="#{login.tip}">请登录</h2><!-- #{login.tip} 这些是之前写的国际化的内容 不要和我一样忘记了,都不知道是什么东西,笑死 --><div class="alert alert-danger" th:if="${param.error}">用户名或密码错误!</div><!-- ${param.error} 接收登录失败后传来的参数,在下面configure方法里 --><div class="form-group"><input type="text" class="form-control user"  name="username" th:placeholder="#{login.username}" placeholder="用户名"></div><div class="form-group"><input type="password" class="form-control user" name="password" th:placeholder="#{login.password}" placeholder="密码"></div><button class="btn btn-primary btn-block user" type="submit" th:text="#{login.button}">登录</button><p class="text-center year">@<span th:text="${currentYear}">2018</span>-<span th:text="${currentYear}+1">2019</span></p><a class="lang" th:href="@{/login(lang='zh_CN')}"> 中文 </a><a class="lang" th:href="@{/login(lang='en_US')}"> English </a></form>
</body>
</html>

继续增加 configure 方法中的内容

package com.zknu.inter.config;import org.springframework.beans.factory.annotation.Autowired;
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;import javax.sql.DataSource;@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate DataSource dataSource;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();String userSQL = "select name,password,valid from t_customer where name = ?";String authoritySQL = "select c.name,a.authority from t_customer c,t_authority a,t_customer_authority ca " +"where ca.customer_id=c.id and ca.authority_id=a.id and c.name=?";auth.jdbcAuthentication().passwordEncoder(encoder).dataSource(dataSource).usersByUsernameQuery(userSQL).authoritiesByUsernameQuery(authoritySQL);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/login/**").permitAll().antMatchers("/details/common/**").hasAnyRole("common","vip").antMatchers("/details/vip/**").hasRole("vip").anyRequest().authenticated().and().formLogin().and().exceptionHandling().accessDeniedPage("/403");http.formLogin().loginPage("/login").permitAll()// 登录页面定为 login 页面,可以直接是html页面,也可以是该html的访问控制类,但上面那个403必须为控制类.usernameParameter("username").passwordParameter("password")/* 接收登录是提交的用户名和密码  必须与前端表单中对应 input的name一致*/.defaultSuccessUrl("/",true)// 默认登录成功后的页面.failureUrl("/login?error");// 登录失败后访问的页面}
}

解释一下这句话

.defaultSuccessUrl("/",true)

为什么加 true:
在我们上一步的测试中发现,我们首先访问 首页,任意点击一个页面后会跳转至登录页面,登录成功后会返回至我们之前访问的那个页面,如果我们不加true,默认成功后的页面会优先访问我们登录前想访问的那个页面;
加true 后会优先访问我们自己定义的访问页面。

defaultSuccessUrl与successForwardUrl
功能一样,都是设置认证成功后的跳转路径。
但是 successForwardUrl 是转发过来,在Controller中需要加一个重定向
https://blog.csdn.net/qq_34975710/article/details/110232128

运行结果
登录页面

登录报错

用户退出登录

有了登录就得有退出登录
在首页中增加注销按钮

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head><meta charset="UTF-8"><title>首页</title><link href="//cdn.staticfile.org/twitter-bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet"><script type="text/javascript" src="//cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script><script type="text/javascript" src="//cdn.staticfile.org/twitter-bootstrap/3.0.1/js/bootstrap.min.js"></script></head>
<body><div class="container"><div class="row clearfix"><div class="col-md-12 column"><nav class="navbar navbar-default navbar-fixed-top" role="navigation"><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav navbar-right"><li><a th:href="@{/login}">登录</a></li><li><form class="logout" th:action="@{/logout}" method="post" style="padding: 5px 15px;"><input type="submit" class="btn btn-warning" value="注销"></form></li><!-- 必须为post方法 --></ul></div></nav><div class="alert alert-danger" style="margin-top: 65px;" th:if="${param.logout}">您已退出登录</div><div class="carousel slide" id="carousel-351237"><ol class="carousel-indicators"><li data-slide-to="0" data-target="#carousel-351237"></li><li data-slide-to="1" data-target="#carousel-351237"></li><li data-slide-to="2" data-target="#carousel-351237" class="active"></li></ol><div class="carousel-inner"><div class="item"><img alt="" th:src="@{/login/images/mt.jpg}" /></div><div class="item"><img alt="" th:src="@{/login/images/xw.jpg}" /></div><div class="item active"><img alt="" th:src="@{/login/images/lx.jpg}" /></div></div> <a class="left carousel-control" href="#carousel-351237" data-slide="prev"><span class="glyphicon glyphicon-chevron-left"></span></a> <a class="right carousel-control" href="#carousel-351237" data-slide="next"><span class="glyphicon glyphicon-chevron-right"></span></a></div></div></div><div class="row clearfix"><div class="col-md-6 column"><h3>向往的生活 第五季</h3><p>《向往的生活》是由湖南卫视推出的大型生活服务纪实节目。节目记录了何炅、黄磊、张艺兴、彭昱畅、张子枫等人一起守拙归园田蘑菇屋,为观众带来一幅“自力更生,自给自足,温情待客,完美生态”的生活画面。</p><a th:href="@{details/common/1}">点击观看</a></div><div class="col-md-6 column"><h3>明星大侦探之名侦探学院 第二季</h3><p>《明星大侦探之名侦探学院 第二季》为《明星大侦探》兄弟篇,节目邀请了颜值与智商兼具的学霸少年进行实景推理“剧本杀”,共度欢乐爆笑的合宿生活,上演高能脑力对决。</p><a th:href="@{details/vip/1}">点击观看</a></div></div>
</div>
</body>
</html>

接着增加configure方法

             http.logout().logoutUrl("/logout").logoutSuccessUrl("/?logout=true");


测试结果

获取登录用户信息

使用SecurityContextHolder获取

在控制类中增加

package com.zknu.inter.controller;import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class MovieController {@GetMapping("/details/{type}/{path}")public String toMovie(@PathVariable("type") String type,@PathVariable("path") String path){return "details/"+type+"/"+path;}@GetMapping("/403")public String authority(){return "403";}@GetMapping("/getUserName")@ResponseBodypublic void user(){SecurityContext context = SecurityContextHolder.getContext();Authentication authentication = context.getAuthentication();UserDetails principal = (UserDetails) authentication.getPrincipal();System.out.println("name:"+principal.getUsername());}
}

因为登录后登录信息就会保存在浏览器中,只以只要不重启或关闭浏览器,你的登录信息就会一直在,所以也提示了我们如果没有重启启动类的情况下想换用户登录,需要清空浏览器的cookie
我用的是QQ浏览器,清理cookie的方法就是


测试方法
先登录,登录后再访问http://localhost:8080/getUserName
控制台会输出当前的用户名

用Security的sec标签获取

增加依赖
必须加版本号

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

sec标签和thymeleaf 的th一样,都是用在前端的。
将前端中登录和注销那里变成这样

记得加
xmlns:sec=“http://www.thymeleaf.org/thymeleaf-extras-springsecurity5”

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head><meta charset="UTF-8"><title>首页</title><link href="//cdn.staticfile.org/twitter-bootstrap/3.0.1/css/bootstrap.min.css" rel="stylesheet"><script type="text/javascript" src="//cdn.staticfile.org/jquery/2.0.0/jquery.min.js"></script><script type="text/javascript" src="//cdn.staticfile.org/twitter-bootstrap/3.0.1/js/bootstrap.min.js"></script></head>
<body><div class="container"><div class="row clearfix"><div class="col-md-12 column"><nav class="navbar navbar-default navbar-fixed-top" role="navigation"><div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"><ul class="nav navbar-nav navbar-right"><li sec:authorize="isAuthenticated()"><a sec:authentication="name"></a></li><li sec:authorize="isAuthenticated()"><form class="logout" th:action="@{/logout}" method="post" style="padding: 5px 15px;"><input type="submit" class="btn btn-warning" value="注销"></form></li><li sec:authorize="isAnonymous()"><a th:href="@{/login}">登录</a></li><!--    <li><a th:href="@{/login}">登录</a></li><li><form class="logout" th:action="@{/logout}" method="post" style="padding: 5px 15px;"><input type="submit" class="btn btn-warning" value="注销"></form></li>--></ul></div></nav><div class="alert alert-danger" style="margin-top: 65px;" th:if="${param.logout}">您已退出登录</div><div class="carousel slide" id="carousel-351237"><ol class="carousel-indicators"><li data-slide-to="0" data-target="#carousel-351237"></li><li data-slide-to="1" data-target="#carousel-351237"></li><li data-slide-to="2" data-target="#carousel-351237" class="active"></li></ol><div class="carousel-inner"><div class="item"><img alt="" th:src="@{/login/images/mt.jpg}" /></div><div class="item"><img alt="" th:src="@{/login/images/xw.jpg}" /></div><div class="item active"><img alt="" th:src="@{/login/images/lx.jpg}" /></div></div> <a class="left carousel-control" href="#carousel-351237" data-slide="prev"><span class="glyphicon glyphicon-chevron-left"></span></a> <a class="right carousel-control" href="#carousel-351237" data-slide="next"><span class="glyphicon glyphicon-chevron-right"></span></a></div></div></div><div class="row clearfix"><div class="col-md-6 column"><h3>向往的生活 第五季</h3><p>《向往的生活》是由湖南卫视推出的大型生活服务纪实节目。节目记录了何炅、黄磊、张艺兴、彭昱畅、张子枫等人一起守拙归园田蘑菇屋,为观众带来一幅“自力更生,自给自足,温情待客,完美生态”的生活画面。</p><a th:href="@{details/common/1}">点击观看</a></div><div class="col-md-6 column"><h3>明星大侦探之名侦探学院 第二季</h3><p>《明星大侦探之名侦探学院 第二季》为《明星大侦探》兄弟篇,节目邀请了颜值与智商兼具的学霸少年进行实景推理“剧本杀”,共度欢乐爆笑的合宿生活,上演高能脑力对决。</p><a th:href="@{details/vip/1}">点击观看</a></div></div>
</div>
</body>
</html>

isAuthenticated():判断用户是否已登录,已登录返回 true
isAuthenticated():判断用户是否未登录,未登录返回true
这两个方法的前缀都是 sec:authorize(注意! 是authorize,不是authority,刚开始我一直写的都是 ty 导致我运行一直不对,然后发现我自己拼错了,英语不好的悲哀啊,唉)
sec:authentication=“name” :获取当前用户的用户名

其他的看这里
https://www.cnblogs.com/jpfss/p/8669000.html

测试结果

访问首页,没有登录时只显示登录按钮,不显示注销按钮;

登陆后显示用户名和注销按钮
注销后又只显示登录按钮

该功能有也可以用上面那个SecurityContextHolder完成
注意,th:if 没有 else,用th:unless替代

将thymeleaf用在js里面

方便页面布局啊跳转啊传参啊什么的。

我们将登录失败传的 error 加一个值 true

在login页面加js,在控制台打印

<script th:inline="javascript">var er = [[${param.error}]];console.log(er);</script>

注意js一定要在html标签内,因为引用的th链接是在html标签上引用的


控制台打印,发现我们接收到的参数都是数组形式。

更多内容可参考
https://blog.csdn.net/mygzs/article/details/52667897

小小白学Springboot(十一)——Security安全管理相关推荐

  1. 跟我学Springboot开发后端管理系统8:Matrxi-Web权限设计实现

    上篇文章讲述了Matrix-web整体实现的权限控制的思路.现在来回顾一下: 首先,用户需要登录,填用户名.密码,后端接收到登录请求,进行用户.密码的校验,校验成功后则根据用户名生成Token,并返回 ...

  2. 跟我学Springboot开发后端管理系统7:Matrxi-Web权限设计

    Matrxi-Web权限设计 对于一个后端系统来说,权限是基础设施,是安全保障.没有权限,系统可能随时面临各种风险,所以权限设计对后端系统来说至关重要.在Javaweb开发中,有很多权限开发的框架,比 ...

  3. 跟着大宇学SpringBoot目录贴

    与君共勉 故不积跬步,无以至千里.不积小流,无以成江海.骐骥一跃不能十步,驽马十驾功在不舍. 谁都是从HelloWorld开始学习的,即使是架构师,也是一样. 纯干货,重实战,贵在积累. 从头开始学S ...

  4. SpringBoot集成security(1)|(security入门)

    SpringBoot集成security(1)|(security入门) 文章目录 SpringBoot集成security(1)|(security入门) @[TOC] 前言 一.Spring Se ...

  5. MINA、Netty、Twisted一起学(十一):SSL/TLS

    什么是SSL/TLS 不使用SSL/TLS的网络通信,一般都是明文传输,网络传输内容在传输过程中很容易被窃听甚至篡改,非常不安全.SSL/TLS协议就是为了解决这些安全问题而设计的.SSL/TLS协议 ...

  6. 跟我学Springboot开发后端管理系统9:AOP+logback+MDC日志输出

    MDC介绍 在比较复杂的应用中,一个请求需要走很多个方法的处理,怎么样才能快速查找一个请求的全部日志呢.在分布式系统中,我们可以用链路追踪,比如zipkin.skywalking去快速查找日志,从而定 ...

  7. 跟我学Springboot开发后端管理系统6:缓存框架Caffeine

    Caffeine是一个基于Java8的高性能缓存框架,号称趋于完美.Caffeine受启发于Guava Cache的API,使用API和Guava是一致的.它借鉴了Guava Cache和Concur ...

  8. 跟我学Springboot开发后端管理系统5:数据库读写分离

    在Matrix-web后台管理系统中,使用到了数据库的读写分离技术.采用的开源的Sharding-JDBC作为数据库读写分离的框架.Matrix-Web后台数据库这一块采用的技术栈如下: 使用Myba ...

  9. 跟我学Springboot开发后端管理系统4:数据库连接池Druid和HikariCP

    上一篇文章主要讲解了如何再Matrix-Web中使用Mybatis-Plus,Mybatis-Plus作为Orm框架,连接数据库需要连接数据库的依赖.WEB 系统高并发环境下,频繁的进行数据库连接操作 ...

最新文章

  1. android SQL 语句
  2. Android 4.0的图形硬件加速及绘制技巧
  3. boost::transpose_graph用法的测试程序
  4. linux 内核模块太大,Linux内核模块文件大小
  5. 用Java中的抽象类扩展抽象类
  6. ASP.NET缓存:方法分析和实践示例
  7. c++课程学习(未完待续)
  8. TensorFlow模型保存和提取方法
  9. FFmpeg发送流媒体的命令(UDP,RTP,RTMP)
  10. 计算机基础知识上机操作excer,excel上机操作题及答案
  11. Latex数学符号输入大全
  12. python对称加密算法库_对称加密算法
  13. python四则运算表达式,用Python自动生成小学四则运算题目2.0版
  14. JUL配置文件进行相关配置
  15. SpringBoot + uni-app开发企业级图书商城系统
  16. 移动端兼容如: 背景图片、页面放大、卡顿、闪退、内阴影
  17. 推荐几个免费的ppt模板网站
  18. 《一封神气的情书》李敖
  19. 前端登陆之cookie篇
  20. 《剑指offer》序——面试流程及面试须知

热门文章

  1. java给图片加水印_Java 为图片添加水印(图片水印,文字水印)
  2. 如何将加密U盘变为普通U盘
  3. Arduino+Proteus 模拟摩尔斯码求救信号
  4. 理解 B 树、B+ 树特点及使用场景
  5. 计算机原理【七】之 输入输出系统
  6. Capture Allegro学习笔记1
  7. rqnoj 682 wikioi 1285 noi2004 郁 闷 的 出 纳 员
  8. SystemVerilog中随机的constrain语法
  9. laraverl框架房源管理
  10. Docker自制CentOS镜像