SpringSecurity菜鸟教程

一:简单配置权限管理

SecurityConfg的配置

package com.example.demo11.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;import java.util.Objects;@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Beanpublic PasswordEncoder passwordEncoder() {return new PasswordEncoder() {@Overridepublic String encode(CharSequence charSequence) {return charSequence.toString();}@Overridepublic boolean matches(CharSequence charSequence, String s) {return Objects.equals(charSequence.toString(), s);}};}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("用户").password("123").roles("vip1").and().withUser("管理员").password("123").roles("vip2").and().withUser("超级管理员").password("123").roles("vip1", "vip2");}//配置忽略掉的 URL 地址,一般用于js,css,图片等静态资源@Overridepublic void configure(WebSecurity web) throws Exception {//web.ignoring() 用来配置忽略掉的 URL 地址,一般用于静态文件web.ignoring().antMatchers("/js/**", "/css/**", "/fonts/**", "/images/**", "/lib/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/css/**", "/js/**", "/images/**").permitAll();//开启运行iframe嵌套页面http.headers().frameOptions().disable();http.authorizeRequests().antMatchers("/level1/vip1").hasRole("vip1").antMatchers("/level2/vip2").hasRole("vip2");//没有权限会到默认的登录页面http.formLogin();}
}

IndexController的代码

package com.example.demo11.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class IndexController {@GetMapping("/index")public String index(){return "index";}@GetMapping("/level1/vip1")public String level1Vip1(){return "level1/vip1";}@GetMapping("/level2/vip2")public String level2Vip1(){return "level2/vip2";}
}

由于没有设置springsecurity全部拦截,主页可以允许所有人访问

二:自定义登录页面,记住密码

1自定义登陆页面
改变SecurityConfig中的配置
这个需要自己写一个登录的接口

 @Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/css/**", "/js/**", "/images/**").permitAll();//开启运行iframe嵌套页面http.headers().frameOptions().disable();http.authorizeRequests().antMatchers("/level1/vip1").hasRole("vip1").antMatchers("/level2/vip2").hasRole("vip2");//任何请求都必须经过身份认证http.authorizeRequests().anyRequest().authenticated();//没有权限会到默认的登录页面http.formLogin()//登录的页面.loginPage("/login").usernameParameter("username")//自定义表单的用户名的name,默认为username.passwordParameter("password")//自定义表单的密码的name,默认为password.loginProcessingUrl("/dologin")//表单请求的地址,一般与form的action属性一致,注意:不用自己写doLogin接口,只要与form的action属性一致即可.successForwardUrl("/index")//登录成功后跳转的页面(重定向).failureForwardUrl("/login")//登录失败后跳转的页面(重定向).and().logout() //开启注销功能.logoutSuccessUrl("/login") //注销后跳转到哪一个页面.clearAuthentication(true)// 配置注销登录请求URL为"/logout"(默认也就是 /logout).clearAuthentication(true) // 清除身份认证信息.invalidateHttpSession(true) //使Http会话无效.permitAll().and().csrf().disable();}
login.html文件

2.记住密码和注销功能

 //开启记住我功能,cookie接收,默认保存两周,自定义接收其前端http.rememberMe().rememberMeParameter("remember");


注销功能:

三:基于数据库自定义的表单验证

1.数据库表
这里的登录认证只涉及到三张表:用户表(user)、角色表(role)、用户角色中间表(user_role)。

/*Navicat Premium Data TransferSource Server         : test3Source Server Type    : MySQLSource Server Version : 80015Source Host           : localhost:3306Source Schema         : test2Target Server Type    : MySQLTarget Server Version : 80015File Encoding         : 65001Date: 31/05/2020 22:01:56
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, 'ROLE_vip0');
INSERT INTO `role` VALUES (2, 'ROLE_vip1');
INSERT INTO `role` VALUES (3, 'ROLE_vip2');
INSERT INTO `role` VALUES (4, 'ROLE_vip3');-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'root', '$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq');
INSERT INTO `user` VALUES (3, '灰太狼', '$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq');
INSERT INTO `user` VALUES (4, '喜羊羊', '$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq');
INSERT INTO `user` VALUES (5, '懒羊羊', '$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq');
INSERT INTO `user` VALUES (6, '小灰灰', '$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq');-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (`id` int(11) NOT NULL AUTO_INCREMENT,`uid` int(11) NULL DEFAULT NULL,`rid` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES (1, 1, 1);
INSERT INTO `user_role` VALUES (2, 1, 2);
INSERT INTO `user_role` VALUES (3, 1, 3);
INSERT INTO `user_role` VALUES (4, 1, 4);
INSERT INTO `user_role` VALUES (5, 3, 2);
INSERT INTO `user_role` VALUES (6, 4, 3);
INSERT INTO `user_role` VALUES (7, 6, 4);
INSERT INTO `user_role` VALUES (8, 5, 1);SET FOREIGN_KEY_CHECKS = 1;

注意:这里的role跟上面的例子相比多加了ROLE_前缀。这是因为之前的role都是通过springsecurity的api赋值过去的,他会自行帮我们加上这个前缀。但是现在我们使用的是自己的数据库里面读取出来的权限,然后封装到自己的实体类中。所以这时候需要我们自己手动添加这个ROLE_前缀。经过测试如果不加ROLE_前缀的话,可以做数据库的认证,但无法做授权

2.建实体类User,注意User需要实现UserDetails接口,并且实现该接口下的7个接口

package com.example.demo11.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements UserDetails {private Integer id;private String userName;private String passWord;private List<Role> roles;//该用户对应的角色/*** 返回用户的权限集合。* @return*/@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {List<SimpleGrantedAuthority> authorities = new ArrayList<>();for (Role role : roles){authorities.add(new SimpleGrantedAuthority(role.getName()));System.out.println(authorities);}return authorities;}/*** 返回账号的密码* @return*/@Overridepublic String getPassword() {return passWord;}/*** 返回账号的用户名* @return*/@Overridepublic String getUsername() {return userName;}/*** 账号是否失效,true:账号有效,false账号失效。* @return*/@Overridepublic boolean isAccountNonExpired() {return true;}/*** 账号是否被锁,true:账号没被锁,可用;false:账号被锁,不可用* @return*/@Overridepublic boolean isAccountNonLocked() {return true;}/*** 账号认证是否过期,true:没过期,可用;false:过期,不可用* @return*/@Overridepublic boolean isCredentialsNonExpired() {return true;}/*** 账号是否可用,true:可用,false:不可用* @return*/@Overridepublic boolean isEnabled() {return true;}
}

角色表实体类Role,这个类不用实现上述接口

package com.zsc.po;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {private Integer id;private String name;//角色的名字
}

接下来做数据库的查询,创建持久层接口(UserMapper和RoleMapper)

package com.example.demo.mapper;import com.example.demo.pojo.Role;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;import java.util.List;@Mapper
@Repository
public interface RoleMapper {/*** 通过用户id获取用户角色集合** @param userId 用户id* @return List<Role> 角色集合*/List<Role> getRolesByUserId(Integer userId);}
package com.example.demo.mapper;import com.example.demo.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;import java.util.List;@Mapper
@Repository
public interface UserMapper {/*** 通过用户名获取用户信息** @param username 用户名* @return User 用户信息*/List<User> getUserByUsername(String username);}

持久层接口对应配置文件(UserMapper.xml和RoleMapper.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.demo.mapper.RoleMapper"><resultMap id="roleMap" type="com.example.demo.pojo.Role"><id column="id" property="id"></id><result column="name" property="name"></result></resultMap><select id="getRolesByUserId" resultMap="roleMap">select * from role r,user_role ur where r.id = ur.rid and ur.uid = #{userId}</select></mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.demo.mapper.UserMapper"><resultMap id="userMap" type="com.example.demo.pojo.User"><id column="id" property="id"></id><result column="username" property="userName"></result><result column="password" property="passWord"></result><collection property="roles" ofType="com.example.demo.pojo.Role"><id property="id" column="rid"></id><result column="rname" property="name"></result></collection></resultMap><select id="getUserByUsername" resultMap="userMap">select * from user  where username = #{username}</select>
</mapper>

源码地址:SpringSecurity

SpringSecurity简单教程(源码开源免费提供)相关推荐

  1. 小程序源码:全网独家小程序版本独立微信社群人脉系统社群空间站最新源码开源+详细教程

    功能介绍: 1.微信社群是一个集发布.展示社群信息.人脉推广的裂变工具/平台. 2.通过人脉广场,将商家信息通过名片进行展示,让资源对接.人脉推广更加便捷高效.为平台带来更多流量,让平台更有价值. 3 ...

  2. 源码交流网,提供50套商业源码免费下载

    源码交流网,提供50套商业源码免费下载 源码交流网(www.100oa.com).改版后重出江湖,50套精品商业源码免费下载,您要做的,就是把本广告在各大技术论坛上发10个同样的广告,好消息让更多的人 ...

  3. 旧版3.1.0版本文章内有新版独立微信社群人脉系统社群空间站最新源码开源+详细教程

    介绍: 3.1.0版本独立微信社群人脉系统社群空间站最新源码开源+详细教程 刚想到3.1.0版本的还没有分享只分享了3.1.1版本和2.8.2版本的现在把3.1.0版本的也分享出来比较完善 功能各有各 ...

  4. 全网独家3.1.2版本独立微信社群人脉系统社群空间站最新源码开源+详细教程

    最新3.1.2版本独立微信社群人脉系统社群空间站最新源码开源+详细教程 3.1.0旧版本传送门:人脉系统3.1.0 3.1.1旧版本传送门:人脉系统3.1.1 功能介绍: 1.微信社群是一个集发布.展 ...

  5. 最新3.1.1版本独立微信社群人脉系统社群空间站最新源码开源+详细教程

    功能介绍: 1.微信社群是一个集发布.展示社群信息.人脉推广的裂变工具/平台. 2.通过人脉广场,将商家信息通过名片进行展示,让资源对接.人脉推广更加便捷高效.为平台带来更多流量,让平台更有价值. 3 ...

  6. wordpres情话小程序源码开源带教程

    a.海报修复 首先必须登录小程序才能生生成海报,如果不能登录请看小程序无法登录解决办法 1.图片域名要放到小程序管理后台的downloadfile域名里,小程序前端的config.js 设置图片的do ...

  7. tr069开源代码文档_tr069简单实现源码分享

    [实例简介] tr069简单实现源码分享 [实例截图] [核心代码] org.slive.tr069.bundle └── org.slive.tr069.bundle ├── build.prope ...

  8. 日志组件Log2Net的介绍和使用(附源码开源地址)

    Log2Net是一个用于收集日志到数据库或文件的组件,支持.NET和.NetCore平台. 此组件自动收集系统的运行日志(服务器运行情况.在线人数等).异常日志.程序员还可以添加自定义日志. 该组件支 ...

  9. 年少痴狂,怀恋曾经的创业岁月,语音识别的应用远远未到高潮,本人的软件源码开源,需要的留下Email 我给大家发

    年少痴狂,怀恋曾经的创业岁月,语音识别的应用远远未到高潮,本人的软件源码开源,需要的留下Email,我给大家发 本人大学时代激情四射,活力太足,同时也不太懂得这个社会的商业规则,大学时代的激情已经退去 ...

  10. 年少痴狂,怀恋曾经的创业岁月,语音识别的应用远远未到高潮,本人的软件源码开源,需要的留下Email,我给大家发

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 年少痴狂 ...

最新文章

  1. 使用TensorRT和Jetson TX1 / TX2部署深度学习推理网络和深度视觉原语的指南 学习五
  2. Valgrind使用【转】
  3. EBS 11i数据库升级(9i-10g)几点事项
  4. 香港四大天王影帝情况(截止2016)
  5. leetcode-无重复字符的最长子串
  6. 鼠标放上超链接显示背景效果
  7. Java泛型面试问题
  8. python字符串find方法(二分钟读懂)
  9. 使用Jmeter对API进行性能测试
  10. loopback(本地回环)接口的作用
  11. matlab中的spline,在MATLAB中与spline(x,y,xi)插值效果相同的命令是( )
  12. 【解决方案】windows系统部分软件变日文
  13. ProcessingJoy —— 油画笔触【JAVA】
  14. CodeBlocks旧版下载
  15. Arduino IDE环境下WeMos D1开发板引脚定义和映射
  16. oracle reorg的意义,Oracle Reorg 的形式与相关的script - 2016-02-26
  17. Windows 查看文件占用
  18. Cisco CCNA系列课程学习
  19. 内外兼修,从增速到增质的触宝新时代
  20. DNS与CDN——前端重点

热门文章

  1. 自己不能跑的车凭什么叫自行车?华为天才少年打造无人驾驶「自行车」
  2. java学习笔记---3
  3. 2019年7月28日解决战网BLZBNTBNA00000005BLZBNTBNA00000006BLZBNTBTS0000005DBLZBNTBTS0000004A 007D0 008A4 00840
  4. html psd设计图,根据PSD登陆页面设计稿切图制作HTML网页全过程
  5. DASCTF2022.07赋能赛 - Pwn easyheap
  6. 发票查验系统帮你轻松解决发票管理各种问题
  7. 用 SIR 模型拟合疫情感染情况
  8. Android 学生管理系统
  9. 汉化破解:Restorator辅助绕过注册码
  10. 金蝶K3服务器安装及配置