Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。
针对springboot项目,常见的配置方案
/*
SecurityConfig配置类
@EnableWebSecurity 开启配置验证
*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
AdminSer adminSer; //管理员服务层
/*
添加管理员账号到SecurityConfig的认证集合中,SecurityConfig会自动根据已存在的账号安排对应的权限
添加账号用法
auth.inMemoryAuthentication().withUser("用户名").passwordEncoder(密码编码模式).password("密码").roles("角色权限")
*/
@Override //认证
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
ArrayList<Admin> allAdmin = adminSer.getAllAdmin(); //获取所有管理员账号
for (Admin admin : allAdmin) {
auth.inMemoryAuthentication()
.withUser(String.valueOf(admin.getAdminId())) //用户名
.passwordEncoder(new BCryptPasswordEncoder()) //密码编码(加密模式)模式
.password(new BCryptPasswordEncoder().encode(admin.getPassword())) //设置密码
.roles(admin.getRoleName()); //角色权限
}
}
/*
根据用户的账号权限,决定用户是否有权限进行访问该接口或资源
工作流程:
当用户在登入页面进行登入时,会被"授权"拦截,并将账号和密码发给"认证","认证"在自己的认证集合中判断该账号是否存在,如果不存在"授权"将重定向到登入页面(默认情况下),如果存在返回该账号的权限,"授权"根据权限放行(允许用户访问)对应的资源和接口,如果没有对应权限将被重定向到登入页面(默认情况下)。
*/
@Override //授权
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/") //antMatchers 资源路径,还可以这样子写antMatchers("/", "/home")
.permitAll() //所有人都可以访问
.antMatchers("/admin/**").hasRole("admin") //hasRole:访问要求的角色权限
.antMatchers("/master/**").hasRole("master") //hasRole:访问要求的角色权限
.and() //连接符,这样子才可用继续使用链式编程
.formLogin() //登入页面配置
.passwordParameter("password") //规定接受的密码参数
.usernameParameter("username") //规定接受的用户名参数
.permitAll() //所有人都可以访问
.and()
.csrf().disable(); //csrf()防止伪站点攻击,disable()启动网站保护
/*
.and
.rememberMe()//验证成功后记住我 原理是用户信息存在cookies,下次访问不需要再输入账号密码
.rememberMeParameter("remember");//规定接受记住我的参数
.and()//分割
.logout()//注销
.logoutSuccessUrl("/")//更改注销后跳转的页面
.permitAll()//所有人可以访问
*/
;
}
}
想要深入学习可以观看下面两个大佬的博客
https://blog.csdn.net/andy_zhang2007/article/details/90511688
https://wangsong.blog.csdn.net/article/details/106068685
官方
Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理。使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大的Web和企业应用程序
易于使用
易于使用是该项目的最终目标。应用程序安全性可能非常令人困惑和沮丧,并被视为“必要的邪恶”。如果您使它易于使用,以使新手程序员可以开始使用它,那么就不必再痛苦了。
全面
Apache Shiro声称没有其他具有范围广度的安全框架,因此它很可能是满足安全需求的“一站式服务”。
灵活
Apache Shiro可以在任何应用程序环境中工作。尽管它可以在Web,EJB和IoC环境中运行,但并不需要它们。Shiro也不要求任何规范,甚至没有很多依赖性。
具有Web功能
Apache Shiro具有出色的Web应用程序支持,允许您基于应用程序URL和Web协议(例如REST)创建灵活的安全策略,同时还提供一组JSP库来控制页面输出。
可插拔
Shiro干净的API和设计模式使它易于与许多其他框架和应用程序集成。您会看到Shiro与Spring,Grails,Wicket,Tapestry,Mule,Apache Camel,Vaadin等框架无缝集成。
支持
Apache Shiro是Apache Software Foundation(Apache软件基金会)的一部分,该组织被证明以其社区的最大利益行事。项目开发和用户群体友好的公民随时可以提供帮助。如果需要,像Katasoft这样的商业公司也可以提供专业的支持和服务。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9GBjKu3n-1625228240900)(F:\笔记\图片\SpringSecurity和Shiro\shiro构造.png)]
Subject:
Subject`它本质上是当前正在执行的用户的特定于安全性的“视图”。虽然“用户”这个词通常意味着一个人,但是它可以是一个人,但它也可以代表第三方服务,守护进程帐户,定时任务或任何类似的东西 ,总之,它可基本上以是任何与软件交互的东西。
Subject
实例都绑定(并要求)到 SecurityManager
。当您与一个Subject
进行交互时,最后都会转换为与 SecurityManager
的交互。
SecurityManager
SecurityManager
是Shiro架构的核心,充当一种“综合的”对象,协调其内部安全组件。但是,一旦为应用程序配置好了SecurityManager及其内部组件对象,它通常不会再被开发人员调用,应用程序开发人员几乎将所有时间花在Subject的
API上。
我们稍后将SecurityManager
详细讨论。但目前最重要的要意识到,当您与Subject
进行交互时,实际上在幕后是SecurityManager
完成所有Subject
安全操作。这反映在上面的基本流程图中。
Realms
领域充当Shiro与应用程序安全数据之间的“桥梁”或“连接器”。当实际与安全相关的数据(如用户帐户)进行交互,以执行身份验证(登录)和授权(访问控制)时,Shiro会从为应用程序配置的一个或多个Realm中查找许多这些程序的安全数据。
详细介绍网站
针对springboot项目
导入依赖
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-spring-boot-web-starterartifactId>
<version>1.5.3version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
创建配置类
创建Realm
public class UserRealm extends AuthorizingRealm {
@Override //授权 当用户进入需要授权页面时触发
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到user对象 (获取正在获取授权的用户)
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
if(user.getUsername().equals("admin")){
info.addStringPermission("admin:v1");//设置当前用户的权限
}
return info;
}
@Override //认证 当用户认证时触发
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken aToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) aToken;
User user = new User("admin","123");
System.out.println("进入认证,用户名:"+token.getUsername()+" 密码:"+token.getPassword());
//账号认证,密码验证shiro来做
if(!token.getUsername().equals(user.getUsername())){
return null; //用户不存在返回null,返回null就是转跳登入页面重新登入
}else {
return new SimpleAuthenticationInfo(user,user.getPassword(),"");//这里的user是用来给授权调用的
}
}
}
创建配置类
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("dwsm") DefaultWebSecurityManager dwsm){
ShiroFilterFactoryBean sffb = new ShiroFilterFactoryBean();
Map<String, String> filterMap = new LinkedHashMap<>();//存放过滤器
/*
anon:无需认证就可以访问
authc:必须认证才可访问
user:必须拥有 记住我 功能才能访问
perms:拥有 某资源的权限 才能访问
role:拥有 某个角色权限 才能访问
*/
filterMap.put("/user","authc");
filterMap.put("/admin","perms[admin:v1]");//添加某资源的权限
sffb.setFilterChainDefinitionMap(filterMap);//设置路径过滤器
sffb.setSecurityManager(dwsm); //设置安全管理器
sffb.setLoginUrl("/tologin");//设置登入页面,跳转/login请求
return sffb;
}
@Bean("dwsm")
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(userRealm); //绑定Realms
return dwsm;
}
@Bean //创建配置好的Realm
public UserRealm userRealm(){
return new UserRealm();
}
}
创建视图
login.html
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<form action="/login">
<p><input type="text" name="username">p>
<p><input type="password" name="password">p>
<p><input type="submit">p>
<p th:text="${msg}">p>
form>
body>
html>
user.html,内容自定义
index.html,内容自定义
admin.html,内容自定义
创建controller类
@Controller
public class MyController {
@RequestMapping("/tologin")
public String toLogin(){
return "login"; //需要对应的login.html
}
@RequestMapping("/user")
public String toUser(){
return "user";//需要对应的user.html,内容自定义
}
@RequestMapping({"/","/index"})
public String toIndex(){
return "index";//需要对应的index.html,内容自定义
}
@RequestMapping("/login")
public String Login(Model model, @RequestParam("username") String username,@RequestParam("password") String password){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try {
subject.login(token);//执行登入认证,成功就往下走,失败抛出异常
return "user";
}catch (UnknownAccountException e){//用户名不存在
model.addAttribute("msg","用户名不存在");
return "login";
}catch (IncorrectCredentialsException e){//密码错误
model.addAttribute("msg","密码错误");
return "login";
}
}
@RequestMapping("/admin")
public String toAdmin(){
return "admin";//需要对应的admin.html,内容自定义
}
}