SpringSecurity
1、Spring Security介绍
介绍
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。
特征
- 对身份验证和授权的全面且可扩展的支持
- 防止攻击,例如会话固定,点击劫持,跨站点请求伪造等
- Servlet API集成
- 与Spring Web MVC的可选集成
- 等等…
2、使用
针对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
1、介绍
Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理。使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大的Web和企业应用程序
2、特征
-
易于使用
易于使用是该项目的最终目标。应用程序安全性可能非常令人困惑和沮丧,并被视为“必要的邪恶”。如果您使它易于使用,以使新手程序员可以开始使用它,那么就不必再痛苦了。
-
全面
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这样的商业公司也可以提供专业的支持和服务。
2、核心组件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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中查找许多这些程序的安全数据。
3、使用
针对springboot项目
-
导入依赖
<!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.5.3</version> </dependency> <!--thymeleaf,不导入这个,访问请求可能会报错--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </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
<!DOCTYPE html> <!--login.html--> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> </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,内容自定义 } }