优点:系统设计时定义好查询工资的权限标识,即使查询工资所需要的角色变化为总经理和部门经理也不需要修改授权代码,系统可扩展性强。
2 基于Session的认证方式
代码演示(略)
3.Spring Security和Shiro的区别
相同点
认证功能,授权功能,加密功能,会话管理,缓存支持,rememberMe功能等
不同点
1、Spring Security 基于Spring 开发,项目若使用 Spring 作为基础,配合 Spring Security 做权限更加方便,而 Shiro 需要和 Spring 进行整合开发;
2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;
3、Spring Security 社区资源相对比 Shiro 更加丰富;
4、Shiro 的配置和使用比较简单,Spring Security 上手复杂些;
5、Shiro 依赖性低,不需要任何框架和容器,可以独立运行.Spring Security 依赖Spring容器;
6、shiro 不仅仅可以使用在web中,它可以工作在任何应用环境中。在集群会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。
3.Spring Security
<!-- 以下是>spring security依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
(2)在config包下定义WebSecurityConfig,安全配置的内容包括:用户信息、密码编码器、安全拦截机制。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//定义用户信息服务(查询用户信息)
@Bean
public UserDetailsService userDetailsService(){
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("zhangsan").password("$2a$10$aFsOFzujtPCnUCUKcozsHux0rQ/3faAHGFSVb9Y.B1ntpmEhjRtru").build());
return manager;
}
//密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//安全拦截机制(最重要)
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/r/**").authenticated()//所有/r/**的请求必须认证通过
.anyRequest().permitAll()//除了/r/**,其它的请求可以访问
.and()
.formLogin()//允许表单登录
.loginPage("/login-view")//登录页面
.loginProcessingUrl("/login")
.successForwardUrl("/login-success")//自定义登录成功的页面地址
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login-view?logout");
}
}
在userDetailsService()方法中,我们返回了一个UserDetailsService给spring容器,Spring Security会使用它来获取用户信息。我们暂时使用InMemoryUserDetailsManager实现类,并在其中分别创建了用户,并设置密码和权限。
authenticated() 保护 URL ,需要用户登录permitAll() 指定 URL 无需保护,一般应用与静态资源文件hasRole(String role) 限制单个角色访问,角色将被增加 “ROLE_” . 所以 ”ADMIN” 将和 “ROLE_ADMIN” 进行比较 .hasAuthority(String authority) 限制单个权限访问hasAnyRole(String… roles) 允许多个角色访问 .hasAnyAuthority(String… authorities) 允许多个权限访问 .access(String attribute) 该方法使用 SpEL 表达式 , 所以可以创建复杂的限制 .hasIpAddress(String ipaddressExpression) 限制 IP 地址或子网
(3)默认根路径请求
@Configuration//就相当于springmvc.xml文件
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("redirect:/login");
}
}
退出地址:http://localhost:8080/security/logout
/**
* 测试资源1
* @return
*/
@GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})
@PreAuthorize("hasAuthority('p1')")//拥有p1权限才可以访问
public String r1(){
return "访问资源1";
}
/**
* 测试资源2
* @return
*/
@GetMapping(value = "/r/r2",produces = {"text/plain;charset=UTF-8"})
@PreAuthorize("hasAuthority('p2')")//拥有p2权限才可以访问
public String r2(){
return "访问资源2";
}
.antMatchers("/r/r1").hasAuthority("p1")
.antMatchers("/r/r2").hasAuthority("p2")
authenticate()方法定义了认证的实现过程,它的参数是一个Authentication,里面包含了登录用户所提交的用户、密码等。而返回值也是一个Authentication,这个Authentication则是在认证成功后,将用户的权限及其他信息重新组装后生成。
这里着重说明一下decide的参数:
vote()方法的返回结果会是AccessDecisionVoter中定义的三个常量之一。ACCESS_GRANTED表示同意,
4.4 会话
/**
* 测试资源1
* @return
*/
@GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})
public String r1(){
return getUsername()+" 访问资源1";
}
//获取当前用户信息
private String getUsername(){
String username = null;
//当前认证通过的用户身份
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//用户身份
Object principal = authentication.getPrincipal();
if(principal == null){
username = "匿名";
}
if(principal instanceof org.springframework.security.core.userdetails.UserDetails){
UserDetails userDetails = (UserDetails) principal;
username = userDetails.getUsername();
}else{
username = principal.toString();
}
return username;
}
4.4.2会话控制
通过以下配置方式对该选项进行配置:
server.servlet.session.timeout = 3600s
expired指session过期,invalidSession指传入的sessionid无效。
- httpOnly:如果为true,那么浏览器脚本将无法访问cookie
- secure:如果为true,则cookie将仅通过HTTPS连接发送
server.servlet.session.cookie.http‐only = trueserver.servlet.session.cookie.secure = true
4.6 退出
链式API提供了调用相应的 LogoutHandler 实现的快捷方式,比如deleteCookies()。
4.5.web授权
因此,登录页面的规则应该在/ admin / **规则之前.例如.
保护 URL 常用的方法有:authenticated() 保护 URL ,需要用户登录permitAll() 指定 URL 无需保护,一般应用与静态资源文件hasRole(String role) 限制单个角色访问,角色将被增加 “ROLE_” . 所以 ”ADMIN” 将和 “ROLE_ADMIN” 进行比较 .hasAuthority(String authority) 限制单个权限访问hasAnyRole(String… roles) 允许多个角色访问 .hasAnyAuthority(String… authorities) 允许多个权限访问 .access(String attribute) 该方法使用 SpEL 表达式 , 所以可以创建复杂的限制 .hasIpAddress(String ipaddressExpression) 限制 IP 地址或子网
4.6.方法授权
以上配置标明readAccount、ffindAccounts方法可匿名访问,post方法需要同时拥有p_transfer和p_read_account权限才能访问,底层使用WebExpressionVoter投票器。