引入依赖(引入后即可启动服务器,会自动进行页面拦截,未登录用户会跳转到默认的登陆页面,账号为user,密码在服务器启动时会在控制台输出:Using generated security password:......)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
修改配置文件application(只在需要定义一个账号和密码的时候进行修改)
#定义账号和密码,这里只能定义一个账号和密码 spring.security.user.name=admin spring.security.user.password=123456
编写service类(基于数据库查询用户时编写该类,使用数据库查询不需要编写基于内存定义的代码)
@Service public class MyUserDetailService implements UserDetailsService { @Autowired private UserMapper userMapper; //注入对应mapper使用sql进行数据库操作 @Autowired private PermissionMapper permissionMapper; //注入权限表mapper进行数据库操作 @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //根据账号查询用户信息,username必须唯一 QueryWrapper<User> wrapper=new QueryWrapper<>(); wrapper.eq("username",username); User user = userMapper.selectOne(wrapper); //在数据库根据username查询该用户新 if(Objects.nonNull(user)){ //判断用户是否存在 //如果存在查询该用户具有的权限 List<Permission> permissions = permissionMapper.selectByUserId(user.getUserid()); //将存放权限的集合转化为返回值要求的集合类型 List<SimpleGrantedAuthority> collect = permissions.stream().map(item -> new SimpleGrantedAuthority(item.getPercode())).collect(Collectors.toList()); //转换集合方法等价于该遍历的方法(两个方法存在一个即可) List<SimpleGrantedAuthority> list=new ArrayList<>() ; for(Permission p:permissions){ SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(p.getPercode()); list.add(simpleGrantedAuthority); } return new org.springframework.security.core.userdetails.User(username,user.getUserpwd(),collect); } return null; } }
编写配置类(在启动类application中使用EnableGlobalMethodSecurity(prePostEnabled=true)开启权限绑定的注解驱动 )
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Bean //设置密码加密器 使用:先new出该对象PasswordEncoder passwordEncoder=new BCryptPasswordEncoder(); public PasswordEncoder passwordEncoder() { //passwordEncoder.encode("密码")进行加密 return new BCryptPasswordEncoder(); //passwordEncoder.matches("密码", 加密后的密码)比较密码是否一致 } @Autowired private MyUserDetailService userDetailService; //注入自定义的service类,用于基于数据库进行用户验证 @Override //基于数据库定义用户,使用该方法后不需要基于内存定义的代码 protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.userDetailsService(userDetailService); } @Override //基于内存定义多用户,定义后配置文件中的账号密码会失效,基于数据库时不使用该方法 protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() //基于内存完成认证和授权 .withUser("user1") //用户名 .password(passwordEncoder().encode("123456")) //密码 .roles("admin") //当前用户具有的角色 .authorities("user:select","user:delete","user:insert","user:update") //当前用户具有的权限 .and() //下一个角色的连接符 .withUser("user2") .password(passwordEncoder().encode("123456")) .roles("user") .authorities("user:select","user:export"); } @Override //一些额外的配置 protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/login.html") //未登录时跳转的登录页面 .loginProcessingUrl("/login") //登录页面提交的处理路径 默认为/login .successForwardUrl("/success") //登录成功跳转的路径 必须为post请求 .failureForwardUrl("/fail") //登录失败跳转的路径 必须为post请求 .permitAll(); //上面的请求路径无需登录 http.exceptionHandling().accessDeniedPage("/403.html") //权限不足时跳转的页面 http.csrf().disable(); //禁用跨域伪造请求的过滤器(必带) http.authorizeRequests().anyRequest().authenticated(); //除了其之上的请求,其他请求都需要登录验证 } }
controller层(权限绑定需在启动类开启绑定注解驱动,使用该绑定就不需要在配置类中进行绑定了)
@GetMapping("info") @PreAuthorize("hasAuthority('user:info')") //资源执行前判断当前用户是否拥有user:info权限 public Authentication info(){ //获取当前用户信息 SecurityContext context = SecurityContextHolder.getContext(); //获取SecurityContext对象 Authentication authentication = context.getAuthentication(); //把用户信息封装到Authontication中 UserDetails principal = (UserDetails) authentication.getPrincipal(); //获取用户账号密码等信息 return authentication; } @GetMapping("insert") @PreAuthorize("hasAuthority('user:select')") //资源执行前判断当前用户是否拥有user:select权限 public String insert(){ System.out.println("添加用户"); return "添加用户"; } @GetMapping("delete") public String delete(){ System.out.println("删除用户"); return "删除用户"; } @GetMapping("update") public String update(){ System.out.println("修改用户"); return "修改用户"; } @GetMapping("select") public String select(){ System.out.println("查询用户"); return "查询用户"; }