目录
一、设置登录系统的账号、密码
二、数据库查询用户名密码
三、自定义登录页面
四、基于角色或权限进行访问控制
(一)hasAuthority 方法
(二)hasAnyAuthority 方法
(三)hasRole 方法
(四)hasAnyRole
五、自定义403页面
六、注解使用
(一)@Secured
(二)@PreAuthorize
(三)@PostAuthorize
(四)@PreFilter
(五)@PostFilter
七、基于数据库的记住我
八、CSRF
一、设置登录系统的账号、密码
方式一,配置文件application.properties
spring.security.user.name=lucy
spring.security.user.password=123
方式二,编写配置类
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();String password = bCryptPasswordEncoder.encode("123");auth.inMemoryAuthentication().withUser("zhangsan").password(password).roles("admin");}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
方式三,通过类实现接口UserDetailService
@Service
public class userDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("role");return new User("zhangsan", new BCryptPasswordEncoder().encode("123"), list);}
}
二、数据库查询用户名密码
引入依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency>
建表sql
create table users(id bigint primary key auto_increment,username varchar(20) unique not null,password varchar(100)
);
数据源配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8username: rootpassword: 123456
实体类users
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Users {private Integer id;private String username;private String password;
}
mapper
@Mapper
public interface UserMapper extends BaseMapper<Users> {
}
修改userDetailService
@Service
public class userDetailsService implements UserDetailsService {@AutowiredUserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {// 使用mapper查询数据库QueryWrapper<Users> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username", s);Users users = userMapper.selectOne(queryWrapper);if (users == null) {throw new UsernameNotFoundException("用户名不存在!");}List<GrantedAuthority> list = AuthorityUtils.commaSeparatedStringToAuthorityList("role");return new User(users.getUsername(), new BCryptPasswordEncoder().encode(users.getPassword()), list);}
}
修改SecurityConfigTest
@Configuration
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
三、自定义登录页面
在配置类SpringSecurity中重写configure方法
@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin() //自定义自己编写的登录页面.loginPage("/login.html") //登录页面设置.loginProcessingUrl("/user/login") //登录访问路径.defaultSuccessUrl("/test/index").permitAll() //登录成功之后,跳转路径.and().authorizeRequests().antMatchers("/", "/test/hello","/user/login").permitAll() // 设置哪些路径可以直接访问,不需要认证.anyRequest().authenticated().and().csrf().disable(); // 关闭csrf防护}
再编写登录页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/user/login" method="post">用户名:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/><input type="submit" value="login"/></form>
</body>
</html>
controlller
@RestController
@RequestMapping("/test")
public class HelloController {@GetMapping("/hello")public String test() {return "hello, security";}@GetMapping("/index")public String index() {return "hello, index";}
}
启动项目后使用的登录页面就是我们编写的 了
四、基于角色或权限进行访问控制
(一)hasAuthority 方法
如果当前的主体具有指定的权限,则返回 true,否则返回 false
设置访问/test/index需要admin角色
给用户添加admin角色
修改角色为别的,不是admin后访问被禁止
(二)hasAnyAuthority 方法
(三)hasRole 方法
底层源码:
给用户添加角色需要加上前缀ROLE_
(四)hasAnyRole
修改配置文件:
五、自定义403页面
在配置类中配置
编写unauth页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>没有访问权限</h1>
</body>
</html>
跳转成功
六、注解使用
(一)@Secured
@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled=true)public class DemosecurityApplication {public static void main(String[] args) {SpringApplication.run(DemosecurityApplication.class, args);}
}
controller
@GetMapping("/update")@Secured({"ROLE_admin"})public String update() {return "hello, update";}
(二)@PreAuthorize
@GetMapping("/update")@PreAuthorize("hasAnyAuthority('admin')")public String update() {return "hello, update";}
(三)@PostAuthorize
@RequestMapping("/testPostAuthorize")
@ResponseBody
@PostAuthorize("hasAnyAuthority('admin')")
public String preAuthorize(){System.out.println("test--PostAuthorize");return "PostAuthorize";
}
(四)@PreFilter
@RequestMapping("getTestPreFilter")
@PreAuthorize("hasRole('ROLE_管理员')")
@PreFilter(value = "filterObject.id%2==0")
@ResponseBody
public List<UserInfo> getTestPreFilter(@RequestBody List<UserInfo> list){list.forEach(t-> {System.out.println(t.getId()+"\t"+t.getUsername());});return list;
}
(五)@PostFilter
@RequestMapping("getAll")
@PreAuthorize("hasRole('ROLE_管理员')")
@PostFilter("filterObject.username == 'admin1'")
@ResponseBody
public List<UserInfo> getAllUser(){ArrayList<UserInfo> list = new ArrayList<>();list.add(new UserInfo(1l,"admin1","6666"));list.add(new UserInfo(2l,"admin2","888"));return list;
}
七、基于数据库的记住我
使用spring security记住登录的用户原理
创建表
CREATE TABLE `persistent_logins` (`username` varchar(64) NOT NULL,`series` varchar(64) NOT NULL,`token` varchar(64) NOT NULL,`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP,PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
配置文件编写数据库的配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8username: rootpassword: 123456
配置类
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="/user/login" method="post">用户名:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/><input type="checkbox" name="remember-me"/>60s内免登录<br/><input type="submit" value="login"/></form>
</body>
</html>