目录
主要流程:
具体实现:
主要流程:
(特殊)1、如果你需要返回json格式字符串,那么你首先需要编写相应的处理器,如果不需要则可直接写配置类
2、编写配置类
3、编写认证授权相关的mapper方法和service方法
4、编写认证和授权逻辑
4.1、编写认证授权逻辑的类,实现UserDetailsService接口,重现loadUserByUserName方法
提示:不要忘记将该类放入spring容器中,不然security无法使用该逻辑
4.2、根据用户名查询用户
4.3、根据用户名查询相关权限
4.4、将用户的权限集合转换为security的权限集合
4.5、构建UserDetails对象,放入用户名、密码、security权限集合
4.6、返回构建好的UserDetails对象
5、编写鉴权配置
6、使用不同权限的用户登录,查看他们是否能访问这些接口
具体实现:
(特殊)1、如果你需要返回json格式字符串,那么你首先需要编写相应的处理器
提示:BaseResult是一个统一返回结果集,这里返回结果只是一个参考,因为我的业务时需要返回json格式字符串,具体处理器如何操作还是看业务
登录成功处理器
//登录成功处理器 public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult baseResult = new BaseResult(200,"登录成功",null);response.getWriter().write(JSON.toJSONString(baseResult));} }
登录失败处理器
//登录失败处理器 public class MyLoginFailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult baseResult = new BaseResult(402,"用户名或密码错误",null);response.getWriter().write(JSON.toJSONString(baseResult));} }
注销成功处理器
//登出成功处理器 public class MyLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult baseResult = new BaseResult(200,"注销成功",null);response.getWriter().write(JSON.toJSONString(baseResult));} }
未登录处理器
//未登录处理器 public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult baseResult = new BaseResult(401,"用户未登录",null);response.getWriter().write(JSON.toJSONString(baseResult));} }
权限不足处理器
//权限不足处理器 public class MyAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult baseResult = new BaseResult(403,"权限不足",null);response.getWriter().write(JSON.toJSONString(baseResult));} }
2、编写配置类
提示1:编写配置类的时候不要忘了PasswordEncoder密码解析器
提示2:登录请求一定要是post请求,否则无法请求无法到达
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {//登录配置http.formLogin().usernameParameter("username")//登录用户名项.passwordParameter("password")//登录密码项.loginProcessingUrl("/admin/login")//登录提交路径.successHandler(new MyLoginSuccessHandler())//登录成功处理器.failureHandler(new MyLoginFailureHandler());//登录失败处理器//权限拦截器配置http.authorizeRequests().antMatchers("/login").permitAll()//登录页面不用拦截.antMatchers("/admin/login").permitAll()//登录路径不用拦截.anyRequest().authenticated();//其他路径都要拦截//注销配置http.logout().logoutUrl("/admin/logout")//注销提交路径.logoutSuccessHandler(new MyLogoutSuccessHandler())//注销成功处理器.invalidateHttpSession(true)//清除session.clearAuthentication(true);//清除认证状态//异常处理http.exceptionHandling().accessDeniedHandler(new MyAccessDeniedHandler())//权限不足处理器.authenticationEntryPoint(new MyAuthenticationEntryPoint());//未登录处理器//关闭csrf防护http.csrf().disable();//开启跨域访问http.cors();}@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();} }
3、编写认证授权相关的mapper方法和service方法,具体跟业务相关
4、编写认证和授权逻辑
编写逻辑的时候需要使用到认证和授权相关的mapper和service,所以我们需要引入service,service中使用了相关mapper
具体流程:
1、编写认证授权逻辑的类,实现UserDetailsService接口,重现loadUserByUserName方法
提示:不要忘记将该类放入spring容器中,不然security无法使用该逻辑
2、根据用户名查询用户
3、根据用户名查询相关权限
4、将用户的权限集合转换为security的权限集合
(这个Permission.getUrl()很重要,它就是用户拥有的权限所对应的url,后期我们编写鉴权配置的时候就是通过这个url去判断该用户是否有对应权限的)
5、构建UserDetails对象,放入用户名、密码、security权限集合
6、返回构建好的UserDetails对象
//认证和授权逻辑 @Service public class MyUserDetailsService implements UserDetailsService {@DubboReference //需要使用到认证授权相关的mapper和serviceprivate AdminService adminService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//根据用户名查询用户Admin admin = adminService.findByUserName(username);if(admin == null){throw new UsernameNotFoundException("用户未找到");}//根据用户名查询权限List<Permission> permissions = adminService.findAllPermission(username);//将我的权限集合转为security的权限集合List<GrantedAuthority> grantedAuthorities = new ArrayList<>();for (Permission permission:permissions) {//拿出权限中的url,方便日后的鉴权grantedAuthorities.add(new SimpleGrantedAuthority(permission.getUrl()));}UserDetails userDetails = User.withUsername(admin.getUsername()).password(admin.getPassword()).authorities(grantedAuthorities).build();return userDetails;} }
5、编写鉴权配置
1、在启动类上方开启注解配置访问权限
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ShoppingManagerApiApplication {public static void main(String[] args) {
SpringApplication.run(ShoppingManagerApiApplication.class, args);
}}
2、在相关控制器上方添加注解,配置需要有的权限
/**
* 分页查询管理员
* @param page 页数
* @param size 每页条数
* @return vo
*/
@PreAuthorize("hasAnyAuthority('/admin/search')")
@GetMapping("/search")
public BaseResult<Page<Admin>> search(int page,int size){
Page<Admin> adminPage = adminService.search(page, size);
return BaseResult.ok(adminPage);
}通过这个注解就会自动判断,当前登录的用户是否有/admin/search权限,这些权限的url都是我们在认证和授权逻辑的时候放入的
6、使用不同权限的用户登录,查看他们是否能访问这些接口