权限管理框架
1.Apache Shiro
对系统安全性能不高使用
可以实现身份验证,授权,密码和会话功能
会存在侵入式设计的危险(引入第三方库的时候,需要修改自己的源码)
2.Spring Security
对系统安全的要求比较高使用
和spring联系在一起,但是不够灵活,不是侵入式的
使用Spring Security认证和授权
pom.xml文件中添加Security的依赖
<!--spring security 组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>-*
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
使用response.getWriter().print(String string)将String类型在响应中转换成Json
启动项目
控制台会自动生成一个密码,默认的账户是user
运行后有一个默认的登录页面
登录之后没有任何访问资源,
怎样做认证(没有注解的方式)
认证和授权都是在一个类里面进行的,继承的WebSecurityConfigurerAdapter,但是必须保证自己定义的这个类贴Configuration注解标志是一个配置类
1.配置数据源,需要将这个对象注入到容器中
需要在内存中自己定义账户和密码,返回的是UserDetailsService,以后在数据库查询,现在只是模拟,在这里必须给用户进行授权,否者创建不了Bean
@Bean
public UserDetailsService userDetailsService() {
//在内存中模拟用户的信息,并设置用户的权限
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(); inMemoryUserDetailsManager.createUser(User.withUsername("root").password("123").authorities("p1").build());
return inMemoryUserDetailsManager;
}
2.密码编码器,将这个对象注入到容器中
使用返回的PasswordEncoder类型做密码编码器,现在没有对密码加密,以后的数据库中的密码加密,否则无法进行匹配
@Bean
public PasswordEncoder passwordEncoder() {
//不对密码加密
return NoOpPasswordEncoder.getInstance();
}
3.定制拦截规则
重写了WebSecurityConfigurerAdapter中的configure方法,在这个方法里面进行登录,登出,页面跳转,授权等配置操作
为了防止csrf(跨站请求伪造,恶意代码放在请求路径上)的发生,限制除了get意外的大多数方法,禁用csrf机制
http.csrf().disable()
对hello这个资源需要认证,没有登录就回到登录页面
http .authorizeRequests().antMatchers("/hello").authenticated()
其他资源不需要认证就直接放行,注意和需要认证的路径书写的顺序,否则全部都会被放行
http.authorizeRequests().antMatchers("/**").permitAll()
修改登录页面的路径
http
.formLogin()
登录的页面
.loginPage("/login.html")
//登录的路径
.loginProcessingUrl("/login")
@RequestMapping("/login")
@ResponseBody
public String login() {
return "登录成功";
}
修改账户密码的名字
//将前端传递的参数进行改名,保持和前端的一致
.usernameParameter("username")
.passwordParameter("password")
修改登录后跳转的页面,此时里面返回的
登录成功后跳转的页面
.successForwardUrl("/main")
//登录成功后的处理器,自定义成功后的处理方式,例如直接输出json数据
.successHandler(new MyAuthenticationSucessHandler("/main.html"))
@RequestMapping("/main")
public String main() {
return "redirect:/main.html";
}
登录失败的处理器实现的是AuthenticationFailureHandler接口
.failureHandler(new MyAuthenticationFailureHandler("/login.html"))
修改登出的路径
http
.logout()
.logoutUrl("/logout")//登出访问的路径
修改登出成功的页面
.logoutSuccessUrl("/logoutSuccess");
@RequestMapping("/logoutSuccess")
@ResponseBody
public String logoutSuccess() {
return "登出成功";
}
常见配置
authenticated() 保护URL,需要用户登录
permitAll() 指定URL无需保护,一般应用于静态资源文件
hasRole(String role) 限制单个角色访问
**hasAnyRole(String… roles)**允许多个角色访问
hasAuthority(String authority) 限制单个权限访问
hasAnyAuthority(String… authorities) 允许多个权限访问.
思考:以上默认的功能(登录检查),使用的过滤器还是拦截器?
拦截器是springMVC的,Security底层是使用过滤器,处理的问题比较仔细
使用配置授权
描述哪些资源需要哪些权限(角色)才能访问
在配置类WebSecurityConfigurerAdapter配置类中,对资源做权限配置
http.authorizeRequests().antMatchers("/r").hasAnyRole("p1") //
.antMatchers().hasAnyAuthority("/r");
使用注解授权
在配置类MyWebSecurityConfiguer贴上**@EnableGlobalMethodSecurity**注解,开启安全注解的功能
prePostEnabled = true 对 @PreAuthorize(“hasAnyAuthority(‘p1’)”)注解的处理
securedEnabled()= true 对 @Secured(“ROLE_r2”)注解的处理
有可能是角色,或者权限的注解
修改注解**@EnableGlobalMethodSecurity(prePostEnabled = true)**里面的参数名称
// @Secured("ROLE_r1")
@PreAuthorize("hasAnyAuthority('p1')")
public String r1(){
return "资源1";
}
@RequestMapping("/r/r2")
@ResponseBody
// @Secured("ROLE_r2")
@PreAuthorize("hasAnyAuthority('p1')")
public String r2(){
return "资源2";
}
描述哪些用户拥有哪些角色(权限)
//在内存中模拟用户的信息,并设置用户的权限
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
inMemoryUserDetailsManager.createUser(User.withUsername("admin").password("123").authorities("p1").roles("r1").build());
inMemoryUserDetailsManager.createUser(User.withUsername("root").password("123").authorities("p2").roles("r1").build());