SpringSecurity学习

阅读: 评论:0

SpringSecurity学习

SpringSecurity学习

目录

 简介:

token和jwt的区别

1.快速入门

1.自定义用户名和密码。

自定义重定向。

2.设置权限管理

3.从路径中获取用户信息

2.SpringSecurity核心组件

SecurityContext : authentication对象的容器。

SecurityContextHolder :

Authentication:

​编辑

UserDetails: 存储用户信息的。

UserDetailsService:

AuthenticationManager

3.配置类开发

权限判断

角色判断

IP判断(我的版本废除了)

access 

4.注解开发(了解)

@secured注解(角色判断)

@PreAuthorize + @PostAuthorize注解

@RemeberMe(前后端分离后,我觉得没必要)

Thymleaf(了解)  

CSRF(了解):

总结


 简介:

springSecuicty是spring的一个安全框架,主要负责处理认证授权的功能。

认证:认证当前用户是哪个用户,并具体那个用户。(是否登录)

授权:授予某个用户访问权限,并判断他到底是否有访问权限。(有无权限执行:VIP)

其他的安全感框架:apache shiro ,强大且已于上手的安全框架

授权:貌似底层就想着一个过滤器,Filter从用户的请求判断是否携带相应的请求体来做出相应的相应。

token和jwt的区别

jwt是token的一种复杂实现。

jwt:  全称 json web token 比较复杂,有头部,载荷、签名组成。载荷中,包括用户信息等,并且服务端用秘钥对Jwt进行签名。发给浏览器端,浏览器端,访问时对jwt进行解密,如果解密成功则就是验证成功。

总结 : jwt是一种更复杂的身份令牌信息。

1.快速入门

我们基于web项目做测试

 1.核心依赖

<dependencies><!-- spring-security依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

2.我们建一个login.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action=""><input type="text" placeholder="用户名"><input type="text" placeholder="密码">
</form></body>
</html>

3.启动springboot项目,访问locahost:8080(你没改端口号的话)

 重定向到了这个页面,同时控制台打印一串类似密码的数字。

 证明security已经成功了。

1.自定义用户名和密码。

自定义重定向。

successForwardUrl(),只能重定向到静态页面。我们点进去发现,

 看得出实际上,我们调用successHanler()方法,然后我们url被封装到这里面。

 卧槽,发现了什么?请求转发,看来我们url就被封装在这里面,被进行请求转发。

那为什么,全url为什么不能跳转,上述构造器,有一个断言,看url,符不符合格式,否则,那个跳转对象拿到是url是null。

嗯,看来,我们就是要自定义一个类实现AuthenticationSuccessHandler接口,借鉴上述并进行重写。

限制使用。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("qhx2004").password("{noop}123456").roles("USER");}
}

2.设置权限管理

@Configuration
@EnableWebSecurity
// 配置security注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//  设置资源对应的访问角色权限.antMatchers("/user/**").hasRole("USER").antMatchers("/admin/**").hasRole("ADMIN").anyRequest().authenticated().and().formLogin().and().httpBasic();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication()// 登录账号匹配权限.withUser("qhx2004").password("{noop}123456").roles("USER").and().withUser("admin").password("{noop}111").roles("ADMIN", "USER");// PassWordEncode}
}

3.从路径中获取用户信息

	@RequestMapping("/info")@ResponseBodypublic String productInfo(){String currentUser = "";Object principl = Context().getAuthentication().getPrincipal();if(principl instanceof UserDetails) {currentUser = ((UserDetails)principl).getUsername();}else {currentUser = String();}return " some product info,用户信息 is: "+currentUser;}

2.SpringSecurity核心组件

SecurityContext : authentication对象的容器。

SecurityContextHolder :

Authentication:

它包括这很多,诸如用户信息、证书、用户权限、用户身份之类的。看方法,几乎使我们用来获取的,看样子他是别人调用我们拿到的。

public interface Authentication extends Principal, Serializable {Collection<? extends GrantedAuthority> getAuthorities();Object getCredentials();Object getDetails();Object getPrincipal(); // 拿去UserDetail对象的boolean isAuthenticated();void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

UserDetails: 存储用户信息的。

public interface UserDetails extends Serializable {Collection<? extends GrantedAuthority> getAuthorities();String getPassword();String getUsername();boolean isAccountNonExpired();boolean isAccountNonLocked();boolean isCredentialsNonExpired();boolean isEnabled();
}

UserDetailsService:

public interface UserDetailsService {UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
public class UserDetailsServiceImpl implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {String password = "1234";// 1.我们来自前端的用户名,会调用数据库进行查询,如果成功!if ("123".equals(username)) {// 失败 ,抛异常throw new UsernameNotFoundException("用户并校验错误!");}// 成功,返回一个User(UserDetails的实现类,我们的用户信息就封装在这个对象里面)对象return new User(username, password, ateAuthorityList("12"));}
}

AuthenticationManager

public interface AuthenticationManager {Authentication authenticate(Authentication authentication) throws AuthenticationException;
}

用来检验你的Authentication对象是否正确的。

3.配置类开发

server:servlet:context-path: /qhx
// 给项目 + 路径前缀

 访问以下资源放行卧槽,反正,我们yml文件整,给项目加了前缀/qhx,看出来区别了。mvc就是专门加了,servletpath

  // 授权认证http.authorizeHttpRequests()// 放行路径资源// 一般匹配.antMatchers("/qhx/login.html").permitAll()// mvc匹配.mvcMatchers("/login").servletPath("qhx").permitAll()// 正则匹配.regexMatchers("/qhx/register").permitAll().anyRequest().authenticated();// 所有请求都必须被认证,必须登录之后被访问。

内置访问方法解析,

权限判断

1.测试

  return new User(username, password, AuthorityUtils.// 登陆之后,我给他admin权限commaSeparatedStringToAuthorityList("admin,ROLE_ADMIN"));}

2. 资源限定权限访问

  .antMatchers("/vip").hasAuthority("admin")// 放行:admin.admiN访问.antMatchers("/vip").hasAnyAuthority("admin", "admiN").anyRequest().authenticated();

角色判断

看出来,规定资源能被什么角色访问,登录之后把相应的角色给你,在这里面,也就是说管理员同时具有管理员和普通用户访问资源的权限。

1.测试

  return new User(username, password, AuthorityUtils.// 这个用户能访问普通用户和管理员角色访问的资源commaSeparatedStringToAuthorityList("qhx,wls,ROLE_ADMIN,ROLE_USER"));}

 2.资源限定角色访问

// 角色管控:限定下面这俩资源,一个管理员访问,另一个普通用户访问.antMatchers("/admin").hasRole("ADMIN").antMatchers("/user").hasAnyRole("ADMIN", "USER").anyRequest().authenticated();

IP判断(我的版本废除了)

access 

我们打开源码,发现实际上是调用同对象的access方法,同理我们也可直接用access调用。

access还支持自定方法。

public class MyServiceImpl implements MyService {@Overridepublic boolean hasProm(HttpServletRequest request, Authentication authentication) {Object principal = Principal(); // 拿到user对象if (principal instanceof UserDetails) {UserDetails userDetails = (UserDetails) principal; // 强转Collection<? extends GrantedAuthority> authorities = Authorities();ains(new RequestURI()));}return false;}
}

4.注解开发(了解)

其实看出来为了迎合发展方向,为了迎合我们的配置,就是静态资源和动态一起过滤,但是呢?随着,前后端分离,但是注解开发也是趋势。

@secured注解(角色判断)

1.启动类加上 EnableGlobalMethodSecurity


@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true) // 开启注解启动角色权限(本质上,我们限制的路径资源访问权限)
public class Sspring1securityApplication {public static void main(String[] args) {SpringApplication.run(Sspring1securityApplication.class, args);}}

2.动态资源加上

@RestController
public class LoginContreoller {@Secured("ROLE_admin") // 管理员权限能访问@GetMapping("/login11")public String login() {System.out.println("执行登录..");return "redirect:main.html";}}

错误:会报500异常,AccessDeniedException(访问被拒绝错误)

@PreAuthorize + @PostAuthorize注解

一个在类和方法执行之前权限判断,一个之后判断。

好家伙之前,我们的权限判断角色控制他都能用,只要输入相应的权限表达式即可。

  //@Secured("ROLE_admin") // 管理员权限能访问@PreAuthorize("hasRole('admin')") // 拥有管理员角色权限才能访问

@RemeberMe(前后端分离后,我觉得没必要)

现在,我们完全不需要记住我,这个关键字,因为默认网站差不多就是一个星期之后需要登录一次,那为什么登陆之后,他怎么判断我们是同一个请求,并且怎么记住一星期呢?

1.通过token来判断的话,我们登录之后,设置一个token被浏览器携带,并在浏览器端计算机硬盘储存一个月。

2.当我们下次登录时,会将token发到服务器端API,如果查询成功,则自动登录。

Thymleaf(了解)  

:模版引擎,能将模版和数据分离,但是又能就和在一起形成特定格式(模版)的产物。

CSRF(了解):

跨域网络协议 、IP地址 、端口 中任意一个不相同,就是跨域请求。

  • http本身无状态。通过cookie来记录客服端身份。在cookie中,会存放session id来识别客户端身份。
  • 在跨域的情况下,session id 可能被第三方恶意劫持,通过这个session id向服务器端发起请求。(也就是伪造了用户身份。)
  • 底层来讲,不就是通过session,cookie来判别用户,访问不同的动态资源。

那么CSRF技术,是通过访问时,同时携带_ken 会与在服务端中的token进行比较,如果成功则允许访问。

总结

SecurityConfig.java

@Configuration
@EnableWebSecurity // 启用security配置
// 自定义配置
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());}@Override// 解决静态资源拦截问题(了解)public void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/asserts/**");web.ignoring().antMatchers("/favicon.ico");}@Overrideprotected void configure(HttpSecurity http) throws Exception {// 1.配置登录页并允许访问(没用了),下面2个参数对应表单,最后一个跳转页面。http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login");//2.配置登出页面http.logout().logoutUrl("/logout").logoutSuccessUrl("/");//3.给API设置权限http.authorizeRequests() // 拥有很多权限.antMatchers("/user/**").hasRole("USER").antMatchers("/admin/**").hasAnyRole("USER", "ADMIN")// 任何请求都需要经过认证.anyRequest().authenticated();// 4.关闭跨域保护http.csrf().disable();}// 密码加密@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}

MyUserDetailsServiceImpl.java

@Configuration
public class MyUserDetailService implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 查询就不可能返回boolean值User user = userMapper.findByUserName(username); // 1.查询数据库// 2.判断有无用户if (user == null) {System.out.println(username + "用户没有注册");throw new UsernameNotFoundException(username + "用户没有注册");}return new org.userdetails.Username(), Password(), getAuthority());}// 获取权限列表public List getAuthority() {//return Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"));ateAuthorityList("ROLE_ADMIN");}}

本文发布于:2024-01-27 17:03:33,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063462271539.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:SpringSecurity
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23