赞
踩
最近学习了SpringSecurity就写一个小小的demo来练习一下,如果帮到你了请点一个赞。
如果有错误的地方一定一定要指出来,万分感谢
1.创建一个非常简单的表
super代表超级管理员的一个权限。
2.引入相关的依赖(springboot的基本依赖没有写)
<!--springsecurity--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.4.5</version> </dependency> <!--thymeleaf模板--> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> <version>3.0.1.RELEASE</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
2.编写yml配置文件
#连接数据库
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/mall?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
如果Mapper.xml与Mapper.class不在同一个包下或者不同名,就必须使用配置mapperLocations指定mapper.xml的位置。
3.在创建的mapper包下创建名字为AdminLoginMapper的接口
package com.taobao.mapper;
import com.taobao.pojo.Admin;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Repository
@Mapper
public interface AdminLoginMapper {
Admin adminLogin(String admin_account);
}
4.编写xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.taobao.mapper.AdminLoginMapper">
<select id="adminLogin" parameterType="String" resultType="com.taobao.pojo.Admin">
SELECT * FROM admin WHERE admin_account = #{admin_account}
</select>
</mapper>
至此关于mybatis的操作完成,本文着重与SpringSecurity就不在对mybatis做详细的讲解了。
5.在resoueces的static下引入静态资源 css js等。
6.在resoueces的template下创建一个login.html登录页。
<!doctype html> <html class="x-admin-sm" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>后台登录</title> <meta name="renderer" content="webkit|ie-comp|ie-stand"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi" /> <meta http-equiv="Cache-Control" content="no-siteapp" /> <link rel="stylesheet" th:href="@{/css/font.css}"> <link rel="stylesheet" th:href="@{/css/login.css}"> <link rel="stylesheet" th:href="@{/css/xadmin.css}"> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="/lib/layui/layui.js" charset="utf-8"></script> <!--[if lt IE 9]> <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script> <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body class="login-bg"> <div class="login layui-anim layui-anim-up"> <div class="message">管理登录</div> <div id="darkbannerwrap"></div> <form method="post" class="layui-form" th:action="@{/login}"> <input name="username" placeholder="用户名" type="text" lay-verify="required" class="layui-input" > <hr class="hr15"> <input name="password" lay-verify="required" placeholder="密码" type="password" class="layui-input"> <hr class="hr15"> <input value="登录" lay-submit lay-filter="login" style="width:100%;" type="submit"> <hr class="hr20" > </form> </div> </body> </html>
这里我用的x-admin模板,不用重点关注只需要关注form表单即可。th:action=“@{}”是thymeleaf中的写法,这里也不做过多讲解。
/login下面会做解释。这里的表单提交方式必须为post,账号密码的属性值必须为uername和password下面会做解释
7.创建实体类
package com.taobao.pojo; public class Admin { private Integer id; private String admin_account; private String admin_password; private String leavl; public Admin() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getAdmin_account() { return admin_account; } public void setAdmin_account(String admin_account) { this.admin_account = admin_account; } public String getAdmin_password() { return admin_password; } public void setAdmin_password(String admin_password) { this.admin_password = admin_password; } public String getLeavl() { return leavl; } public void setLeavl(String leavl) { this.leavl = leavl; } @Override public String toString() { return "Admin{" + "id=" + id + ", admin_account='" + admin_account + '\'' + ", admin_password='" + admin_password + '\'' + ", leavl='" + leavl + '\'' + '}'; } }
8.编写SpringSecurity的配置
a.使用@EnableWebSecurity注解,开启Security同时说明这个Configuration类。
b.继承WebSecurityConfigurerAdapter这个类
c.重写configure(HttpSecurity http) 和 configure(HttpSecurity http) 两个方法
package com.taobao.security; 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.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { //下面会讲到,别急 @Autowired private UserDetailsService userDetailsService; //授权 @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() //自定义的登录页面,不写这个会跳到SpringSecurity自己内置的登录页面 .loginPage("/AdminLogin") .loginProcessingUrl("/user/login") .defaultSuccessUrl("/admin/index").permitAll() //任何请求都需要授权 .and().authorizeRequests() .antMatchers("/","/user/login").permitAll() .antMatchers("/admin/index").hasAnyAuthority("super") //任何请求都不需要授权 .anyRequest().authenticated() //关闭csrf防护 .and().csrf().disable(); } //认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //在数据库中获取数据,对密码进行验证,不对密码加密会报错。 auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); } }
9.创建一个service类实现UserDetailsService接口
package com.taobao.service.impl; import com.taobao.mapper.AdminLoginMapper; import com.taobao.pojo.Admin; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import java.util.List; //创建service实现UserDetailsService接口 @Service("userDetailsService") public class AdminDetailsServiceImpl implements UserDetailsService { @Autowired private AdminLoginMapper adminLoginMapper; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { //通过用户名在数据库中查询 Admin admin = adminLoginMapper.adminLogin(s); //如果admin为空说明用户名错误,抛出一个异常 if(admin==null){ throw new UsernameNotFoundException("用户名不存在!"); } //获取该账号的权限 List<GrantedAuthority> atuhs = AuthorityUtils.commaSeparatedStringToAuthorityList(admin.getLeavl()); //查询数据库返回的user对象,密码认证交给security做,密码必须加密。 return new User(admin.getAdmin_account(),new BCryptPasswordEncoder().encode(admin.getAdmin_password()),atuhs); } }
这个类就是我们上面@Autowired的内个类
关于.loginProcessingUrl("/login")的意思登陆访问路径:提交表单之后跳转的地址,可以看作一个中转站,这个步骤就是验证user的一个过程
我的理解是 表单提交到一个controller 这个controller应该调用AdminDetailServiceImpl 。但是这个过程security已经帮我们做了,这里随便写一个地址就好了只需要和action中的保持一直
关于defaultSuccessUrl();百度了一下得到了以下的答案:(原文链接:https://www.xttblog.com/?p=4994)
其实我们通过 defaultSuccessUrl 和 successForwardUrl 的字面意思都能够理解他们的作用。
defaultSuccessUrl 有一个重载的方法,如果我们在 defaultSuccessUrl 中指定登录成功的跳转页面为 /index,此时分两种情况,如果你是直接在浏览器中输入的登录地址,登录成功后,就直接跳转到 /index,如果你是在浏览器中输入了其他地址,例如 http://localhost:8080/xttblog,结果因为没有登录,又重定向到登录页面,此时登录成功后,就不会来到 /index ,而是来到 /xttblog 页面。
defaultSuccessUrl 就是说,它会默认跳转到 Referer 来源页面,如果 Referer 为空,没有来源页,则跳转到默认设置的页面。
successForwardUrl 表示不管你是从哪里来的,登录后一律跳转到 successForwardUrl 指定的地址。例如 successForwardUrl 指定的地址为 /index ,你在浏览器地址栏输入 http://localhost:8080/codedq,如果你还没有登录,将会重定向到登录页面,当你登录成功之后,就会服务端跳转到 /index 页面;或者你直接就在浏览器输入了登录页面地址,登录成功后也是来到 /index。
defaultSuccessUrl 另外一个重载方法,第二个参数如果输入为 true,则效果和 successForwardUrl 一致。
一般来说,我们使用 defaultSuccessUrl 就够了。而且体验也比较好,特殊情况下,我们才使用 successForwardUrl。
loginPage源码的注释中已经说明,login.html 配置提交请求及方式,方式必须为post:
看User类的源码可以知道form表单的账号密码属性必须是username,password.
本人功力尚浅,道行不够。写的还不尽如人意,大家请见谅,对于错误的地方大家一定要给我指出来,我会虚心接收。谢谢
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。