Spring Security 入门(基本使用)

Spring Security 入门(基本使用)
这几天看了下b站关于 spring security 的学习视频,不得不说 spring security 有点复杂,脑袋有点懵懵的,在此整理下学习内容。

1、入门
1.1、什么是 spring security
spring security 是一个比 shiro 更加强大的安全管理框架,权限颗粒度更细。
源自于 spring 家族,能跟 springboot 无缝整合,对 oauth2 的支持也更好。
1.2、依赖配置

org.springframework.boot
spring-boot-starter-security

1.3、测试接口
添加一个简单的 /hello 接口:

@RequestMapping("/hello")
@ResponseBody
public String hello() {
return “恭喜你登录成功”;
}
启动项目,访问 /hello 接口,会发现自动跳转到 spring security 提供的登录页面:

image-20210513103731379

默认的 username 为 :user,password 在项目启动时随机生成,具体如下:

image-20210513104009820

登录成功后即可访问 /hello接口。

2、自定义登录页面、登录成功处理器、登录失败处理器、异常处理器、权限逻辑
项目结构如下:

image-20210514174013950

2.1、自定义登录页面
1、登录页面 login.html :

登陆 用户名:
密码:
立即登陆 2、登录成功跳转页 main.html Title 登录成功!!! 跳转权限页 3、登录失败跳转页 error.html Title 登录失败,请重新登录 跳转 4、权限页 main1.html

**main.html **如果有权限,则能访问该页面,否则报 403

Title 权限控制!!! 2.2、自定义登录逻辑 自定义登录逻辑主要用于对用户名和密码进行校验,需要实现 UserDetailService 接口

@Service
public class UserDetailServiceImpl implements UserDetailsService {

@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    System.out.println("=======执行自定义登录逻辑====");
    //校验用户名,实际环境中需要从数据库查询
    if (!username.equals("admin")) {
        throw new UsernameNotFoundException("用户不存在");
    }
    //比较密码,实际需要从数据库取出原密码校验,框架会自动读取登录页面的密码
    String password = bCryptPasswordEncoder.encode("123456");
    //返回UserDetails,实际开发中可拓展UserDetails
    return new User(username, password, 
                    //自定义权限
                    AuthorityUtils.commaSeparatedStringToAuthorityList("permission1"));
}

}
2.3、自定义登录成功处理器
登录成功处理器实现 AuthenticationSuccessHandler 接口

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

private String url;

public MyAuthenticationSuccessHandler(String url) {
    this.url = url;
}

@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    //获取IP地址
    System.out.println(request.getRemoteAddr());
    //获取认证用户信息
    User user = (User) authentication.getPrincipal();
    System.out.println("=====" + user.getAuthorities());
    //重定向
    response.sendRedirect(url);
}

}
2.4、自定义登录失败处理器
登录失败处理器实现 AuthenticationFailureHandler接口

public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {

private String url;

public MyAuthenticationFailureHandler(String url) {
    this.url = url;
}

@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
    //重定向
    response.sendRedirect(url);
}

}
2.5、自定义异常处理器
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
//响应状态403
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
//返回格式
response.setHeader(“Content-Type”, “application/json;charset=utf-8”);
PrintWriter writer = response.getWriter();
writer.write("{status: “error”,“msg”: “权限不足,请联系管理员”}");
writer.flush();
writer.close();
}
}
2.6、配置 Spring Security
该类是 Spring Security 的配置类, 继承 WebSecurityConfigurerAdapter

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private MyAccessDeniedHandler myAccessDeniedHandler;

/**
 * 指定密码加密的方法
 *
 * @return
 */
@Bean
public BCryptPasswordEncoder getPasswordEncode() {
    return new BCryptPasswordEncoder();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    //表单提交
    http.formLogin()
            //自定义用户名和密码参数
            .usernameParameter("username123")
            .passwordParameter("password123")
            //自定义登录页面
            .loginPage("/showLogin")
            //必须和表单提交的接口一样,执行自定义登录逻辑
            .loginProcessingUrl("/login")
            //自定义登录成功处理器
            .successHandler(new MyAuthenticationSuccessHandler("/main.html"))
            //自定义登录失败处理器
            .failureHandler(new MyAuthenticationFailureHandler("/error.html"));
    
    //授权
    http.authorizeRequests()
            //放行/login.html,不需要认证
            .antMatchers("/showLogin").permitAll()
            //放行/error.html,不需要认证
            .antMatchers("/error.html").permitAll()
            //基于权限判断
            .antMatchers("/main1.html").hasAuthority("permission1")
            //所有请求必须认证
            .anyRequest().authenticated();
    
    //异常处理器
    http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);

    //关闭csrf防护
    http.csrf().disable();
}

/**
 * 放行静态资源,css,js,images
 * 
 * @param web
 * @throws Exception
 */
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/css/**", "/js/**")
    .antMatchers("/**/*.png");
}

}
2.7、运行测试
1、运行后访问 http://localhost:8080/login.html,加载的自定义登录页面如下:

注意我在前面的自定义登录逻辑中写死了 username: admin和password:123456

image-20210513145444184

2、点击立即登陆按钮,根据登录成功处理器重定向到登录成功页 main.html:

image-20210513145901250

3、前面的代码中,如果登录成功则拥有permission1权限,而访问权限页刚好需要 permission1 权限,

点击跳转权限页,来到权限页** main1.html**:

image-20210513150430940

4、修改登录成功的权限为 permission2,

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("===执行自定义登录逻辑");
//校验用户名,实际环境中需要从数据库查询
if (!username.equals(“admin”)) {
throw new UsernameNotFoundException(“用户不存在”);
}
//比较密码,实际需要从数据库取出原密码校验,框架会自动读取登录页面的密码
String password = bCryptPasswordEncoder.encode(“123456”);
//返回UserDetails,实际开发中可拓展UserDetails
return new User(username, password,
//修改权限为permisson2
AuthorityUtils.commaSeparatedStringToAuthorityList(“permission2”));
}
再次访问需要 permission1 权限的权限页,打印以下错误:

image-20210513154239657

5、如果 username 或者 password 错误,根据登录失败处理器重定向到登录失败页 error.html:

image-20210513151019099

3、自定义用户退出登录
3.1、默认的退出登录
spring security 有默认的退出登录接口,直接访问 /logout 接口,就能实现退出登录,下面是简单演示:

main.html 添加退出登录的访问链接logout:

Title 登录成功!!! 退出 跳转权限页 直接就能退出了,简不简单呢?默认跳转到登录页:

image-20210513171702339

仔细观察,发现访问路径拼接了 ?logout 字符串,查看源码可以发现默认的配置如下:

image-20210513172226418

3.2、自定义退出登录
如果默认的退出登录无法满足,可以自定义处理器来解决。

3.2.1、自定义 LogoutHandler
默认情况下清除认证信息 (clearAuthentication),和Session 失效(invalidateHttpSession) 已经由内置的SecurityContextLogoutHandler 来完成。

这个 LogoutHandle 主要用来处理用户信息。

/**

  • 登出接口处理器
    */
    public class MyLogoutHandler implements LogoutHandler {
    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
    User user = (User) authentication.getPrincipal();
    //执行用户信息操作,如记录用户下线时间…
    }
    }
    3.2.2、自定义 LogoutSuccessHandler
    这个 LogoutSuccessHandler 用于返回响应信息给前端,可以返回 json、重定向页面。

注意配置这个处理器之后,就不需要配置 logoutSuccessUrl了。

/**

  • 登出成功处理器
    */
    public class MyLogoutSuccessHandler implements LogoutSuccessHandler {

    private String url;

    public MyLogoutSuccessHandler(String url) {
    this.url = url;
    }
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    //重定向
    response.sendRedirect(url);
    }
    }
    3.3.3、spring security 添加配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    //表单提交
    http.formLogin()
    //自定义用户名和密码参数
    .usernameParameter(“username123”)
    .passwordParameter(“password123”)
    //自定义登录页面
    .loginPage("/login.html")
    //必须和表单提交的接口一样,执行自定义登录逻辑
    .loginProcessingUrl("/login")
    //自定义登录成功处理器
    .successHandler(new MyAuthenticationSuccessHandler("/main.html"))
    //自定义登录失败处理器
    .failureHandler(new MyAuthenticationFailureHandler("/error.html"));
    //授权
    http.authorizeRequests()
    //放行/login.html,不需要认证
    .antMatchers("/login.html").permitAll()
    //放行/error.html,不需要认证
    .antMatchers("/error.html").permitAll()
    //基于权限判断
    .antMatchers("/main1.html").hasAuthority(“permission1”)
    //所有请求必须认证
    .anyRequest().authenticated();

    //异常处理器
    http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);

    //登出
    http.logout()
    //登出接口,与表单访问接口一致
    .logoutUrl("/signLogout")
    //登出处理器
    .addLogoutHandler(new MyLogoutHandler())
    //登出成功后跳转的页面
    .logoutSuccessHandler(new MyLogoutSuccessHandler("/login.html"));

    //关闭csrf防护
    http.csrf().disable();
    }
    3.3.4、修改登出接口
    main.html 修改如下:

Title 登录成功!!! 退出 跳转权限页 运行测试后,返回 localhost://8080/login.html

4、基于注解的权限控制
4.1、权限注解参数
关于权限的注解参数共有三个:

@PreAuthorize:方法执行前进行权限检查
@PostAuthorize:方法执行后进行权限检查
@Secured:类似于 @PreAuthorize
4.2、启动类添加 @EnableGlobalMethodSecurity
启动类配置如下:

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SpringSecurityStudyApplication {

public static void main(String[] args) {
    SpringApplication.run(SpringSecurityStudyApplication.class, args);
}

}
4.3、运行测试
4.3.1、修改 spring security 和 自定义登录逻辑
successHander(登录成功处理器) 修改为 successForwardUrl(登录成功访问路径),删除 permission1的权限判断,改成访问接口时进行权限判断。

@Override
protected void configure(HttpSecurity http) throws Exception {
//表单提交
http.formLogin()
//自定义用户名和密码参数
.usernameParameter(“username123”)
.passwordParameter(“password123”)
//自定义登录页面
.loginPage("/login.html")
//必须和表单提交的接口一样,执行自定义登录逻辑
.loginProcessingUrl("/login")
//登录成功跳转的页面,post请求
.successForwardUrl("/toMain")
//自定义登录失败处理器
.failureHandler(new MyAuthenticationFailureHandler("/error.html"));
//授权
http.authorizeRequests()
//放行/login.html,不需要认证
.antMatchers("/login.html").permitAll()
//放行/error.html,不需要认证
.antMatchers("/error.html").permitAll()
//所有请求必须认证
.anyRequest().authenticated();

//异常处理器
http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);

//登出
http.logout()
    //登出接口,与表单访问接口一致
    .logoutUrl("/signLogout")
    //登出处理器
    .addLogoutHandler(new MyLogoutHandler())
    //登出成功后跳转的页面
    .logoutSuccessHandler(new MyLogoutSuccessHandler("/login.html"));

//关闭csrf防护
http.csrf().disable();

}
自定义登录逻辑如下:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//校验用户名,实际环境中需要从数据库查询
if (!username.equals(“admin”)) {
throw new UsernameNotFoundException(“用户不存在”);
}
//比较密码,实际需要从数据库取出原密码校验,框架会自动读取登录页面的密码
String password = bCryptPasswordEncoder.encode(“123456”);
//返回UserDetails,实际开发中可拓展UserDetails
return new User(username, password,
//自定义权限
AuthorityUtils.commaSeparatedStringToAuthorityList(“permission1”));
}
4.3.2、添加测试接口
//登录成功跳转页
@PostMapping("/toMain")
//判断是否拥有permission1的权限
@PreAuthorize(“hasPermission(‘permission1’)”)
public String toMain() {
//获得认证用户信息
Object object = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (object instanceof UserDetails) {
//进行一系列操作
}
return “redirect:main.html”;
}
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值