经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
springboot整合springsecurity最完整,只看这一篇就够了
来源:cnblogs  作者:QianTLL  时间:2021/4/12 10:01:44  对本文有异议

本人结合其他博客和自己查询的资料,一步一步实现整合了security安全框架,其中踩过不少的坑,也有遇到许多不懂的地方,为此做个记录。

开发工具:ide、数据库:mysql5.7、springboot版本:2.3.7

个人对Spring Security的执行过程大致理解(仅供参考)

 

 

使用Spring Security很简单,只要在pom.xml文件中,引入spring security的依赖就可以了

pom配置:

  1. <dependency>
  2.   <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-security</artifactId>
  4. </dependency>

这个时候我们不在配置文件中做任何配置,随便写一个Controller 

  1. @RestController
  2. public class TestController {
  3. @GetMapping("/hello")
  4. public String request() {
  5. return "hello";
  6. }
  7. }

启动项目,我们会发现有这么一段日志

此时表示Security生效,默认对项目进行了保护,我们访问该Controller中的接口(http://localhost:8080/securitydemo/hello),会见到如下登录界面(此界面为security框架自带的默认登录界面,后期不用可以换成自定义登录界面)

 这里面的用户名和密码是什么呢?此时我们需要输入用户名:user,密码则为之前日志中的"19262f35-9ded-49c2-a8f6-5431536cc50c",输入之后,我们可以看到此时可以正常访问该接口

 

在老版本的Springboot中(比如说Springboot 1.x版本中),可以通过如下方式来关闭Spring Security的生效,但是现在Springboot 2中已经不再支持

  1. security:
  2. basic:
  3. enabled: false

springboot2.x后可以在启动类中设置

1、配置基于内存的角色授权和认证信息

  1.1目录

  

  1.2 WebSecurityConfg配置类

  Spring Security的核心配置类是 WebSecurityConfigurerAdapter抽象类,这是权限管理启动的入口,这里我们自定义一个实现类去实现它。

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description SpringSecurity安全框架配置
  5. */
  6. @Configuration
  7. @EnableWebSecurity//开启Spring Security的功能
  8. //prePostEnabled属性决定Spring Security在接口前注解是否可用@PreAuthorize,@PostAuthorize等注解,设置为true,会拦截加了这些注解的接口
  9. @EnableGlobalMethodSecurity(prePostEnabled=true)
  10. public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
  11. @Override
  12. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  13. /**
  14. * 基于内存的方式,创建两个用户admin/123456,user/123456
  15. * */
  16. auth.inMemoryAuthentication()
  17. .withUser("admin")//用户名
  18. .password(passwordEncoder().encode("123456"))//密码
  19. .roles("ADMIN");//角色
  20. auth.inMemoryAuthentication()
  21. .withUser("user")//用户名
  22. .password(passwordEncoder().encode("123456"))//密码
  23. .roles("USER");//角色
  24. }
  25. /**
  26. * 指定加密方式
  27. */
  28. @Bean
  29. public PasswordEncoder passwordEncoder(){
  30. // 使用BCrypt加密密码
  31. return new BCryptPasswordEncoder();
  32. }
  33. }

  1.3 MainController控制器接口

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description 主控制器
  5. */
  6. @RestController
  7. public class MainController {
  8. @GetMapping("/hello")
  9. public String printStr(){
  10. System.out.println("hello success");
  11. return "Hello success!";
  12. }
  13. }

这样重新运行后我们就可以通过admin/123456、user/123456两个用户登录了。

当然,你也可以基于配置文件创建用户账号,在pom.xml中添加:

 2、配置基于数据库的认证信息和角色授权

  2.1 目录

   2.2  CustomUserDetailsService实现类

UserDetailsService是需要实现的登录用户查询的service接口,实现loadUserByUsername()方法,这里我们自定义CustomUserDetailsService实现类去实现UserDetailsService接口

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description
  5. */
  6. @Component
  7. public class CustomUserDetailsService implements UserDetailsService {
  8. @Resource
  9. private UserInfoService userInfoService;
  10. @Resource
  11. private PasswordEncoder passwordEncoder;
  12. @Override
  13. public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
  14. /**
  15. * 1/通过userName 获取到userInfo信息
  16. * 2/通过User(UserDetails)返回details。
  17. */
  18. //通过userName获取用户信息
  19. UserInfo userInfo = userInfoService.getUserInfoByUsername(userName);
  20. if(userInfo == null) {
  21. throw new UsernameNotFoundException("not found");
  22. }
  23. //定义权限列表.
  24. List<GrantedAuthority> authorities = new ArrayList<>();
  25. // 用户可以访问的资源名称(或者说用户所拥有的权限) 注意:必须"ROLE_"开头
  26. authorities.add(new SimpleGrantedAuthority("ROLE_"+ userInfo.getRole()));
  27. User userDetails = new User(userInfo.getUserName(),passwordEncoder.encode(userInfo.getPassword()),authorities);
  28. return userDetails;
  29. }
  30. }
  1. WebSecurityConfg配置类:
  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description SpringSecurity安全框架配置
  5. */
  6. @Configuration
  7. @EnableWebSecurity//开启Spring Security的功能
  8. //prePostEnabled属性决定Spring Security在接口前注解是否可用@PreAuthorize,@PostAuthorize等注解,设置为true,会拦截加了这些注解的接口
  9. @EnableGlobalMethodSecurity(prePostEnabled=true)
  10. public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
  11. /**
  12. * 指定加密方式
  13. */
  14. @Bean
  15. public PasswordEncoder passwordEncoder(){
  16. // 使用BCrypt加密密码
  17. return new BCryptPasswordEncoder();
  18. }
  19. }

对于通过userName获取用户信息的服务层,持久层和数据库语句就不介绍了,这里使用的是SSM框架,使用mybaits。

  2.3 数据库设计

 

 角色表 roles

用户表 user

用户角色关系表 roles_user

 3、自定义表单认证登录

  3.1 目录

  

   3.2  WebSecurityConfg核心配置类

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description spring-security权限管理的核心配置
  5. */
  6. @Configuration
  7. @EnableWebSecurity//开启Spring Security的功能
  8. //prePostEnabled属性决定Spring Security在接口前注解是否可用@PreAuthorize,@PostAuthorize等注解,设置为true,会拦截加了这些注解的接口
  9. @EnableGlobalMethodSecurity(prePostEnabled=true)
  10. public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
  11. @Resource
  12. private AuthenticationSuccessHandler loginSuccessHandler; //认证成功结果处理器
  13. @Resource
  14. private AuthenticationFailureHandler loginFailureHandler; //认证失败结果处理器
  15. //http请求拦截配置
  16. @Override
  17. protected void configure(HttpSecurity http) throws Exception {
  18. http.headers().frameOptions().disable();//开启运行iframe嵌套页面
  19. http//1、配置权限认证
  20. .authorizeRequests()
  21. //配置不拦截路由
  22. .antMatchers("/500").permitAll()
  23. .antMatchers("/403").permitAll()
  24. .antMatchers("/404").permitAll()
  25. .antMatchers("/login").permitAll()
  26. .anyRequest() //任何其它请求
  27. .authenticated() //都需要身份认证
  28. .and()
  29. //2、登录配置表单认证方式
  30. .formLogin()
  31. .loginPage("/login")//自定义登录页面的url
  32. .usernameParameter("username")//设置登录账号参数,与表单参数一致
  33. .passwordParameter("password")//设置登录密码参数,与表单参数一致
  34. // 告诉Spring Security在发送指定路径时处理提交的凭证,默认情况下,将用户重定向回用户来自的页面。登录表单form中action的地址,也就是处理认证请求的路径,
  35. // 只要保持表单中action和HttpSecurity里配置的loginProcessingUrl一致就可以了,也不用自己去处理,它不会将请求传递给Spring MVC和您的控制器,所以我们就不需要自己再去写一个/user/login的控制器接口了
  36. .loginProcessingUrl("/user/login")//配置默认登录入口
  37. .defaultSuccessUrl("/index")//登录成功后默认的跳转页面路径
  38. .failureUrl("/login?error=true")
  39. .successHandler(loginSuccessHandler)//使用自定义的成功结果处理器
  40. .failureHandler(loginFailureHandler)//使用自定义失败的结果处理器
  41. .and()
  42. //3、注销
  43. .logout()
  44. .logoutUrl("/logout")
  45. .logoutSuccessHandler(new CustomLogoutSuccessHandler())
  46. .permitAll()
  47. .and()
  48. //4、session管理
  49. .sessionManagement()
  50. .invalidSessionUrl("/login") //失效后跳转到登陆页面
  51. //单用户登录,如果有一个登录了,同一个用户在其他地方登录将前一个剔除下线
  52. //.maximumSessions(1).expiredSessionStrategy(expiredSessionStrategy())
  53. //单用户登录,如果有一个登录了,同一个用户在其他地方不能登录
  54. //.maximumSessions(1).maxSessionsPreventsLogin(true) ;
  55. .and()
  56. //5、禁用跨站csrf攻击防御
  57. .csrf()
  58. .disable();
  59. }
  60. @Override
  61. public void configure(WebSecurity web) throws Exception {
  62. //配置静态文件不需要认证
  63. web.ignoring().antMatchers("/static/**");
  64. }
  65. /**
  66. * 指定加密方式
  67. */
  68. @Bean
  69. public PasswordEncoder passwordEncoder(){
  70. // 使用BCrypt加密密码
  71. return new BCryptPasswordEncoder();
  72. }
  73. }

踩坑点1:登录页面接口/login和登录验证接口/user/login,这里是自己之前一直搞错的重点,这里就用网上的图片展示了

踩坑点2:springboot配置spring security 静态资源不能访问

security的配置:在类WebSecurityConfig继承WebSecurityConfigurerAdapter,这个类是我们在配置security的时候,对我们请求的url及权限规则的一些认证配置。具体的不说了,这里主要是静态资源的问题。

在这个类中我们会重写一些方法,其中就有一个方法,可以为我们配置一下静态资源不需要认证。

  1. @Override
  2. public void configure(WebSecurity web) throws Exception {
  3. //配置静态文件不需要认证
  4. web.ignoring().antMatchers("/static/**");
  5. }

页面的引用如下:

  1. <link rel="stylesheet" th:href="@{static/layui/css/layui.css}">

之后我们启动项目:看到css并没有生效

 这时候仅仅通过spring security配置是不够的,我们还需要去重写addResourceHandlers方法去映射下静态资源,这个方法应该很熟悉了,我们通过springboot添加拦截器的时候就会用到这个。

写一个类WebMvcConfig继承WebMvcConfigurationSupport,注意spring boot2版本和1版本是不一样的,spring boot1版本继承的WebMvcConfigurerAdapter在spring boot2版本中已经提示过时了

  1. @Configuration
  2. public class WebMvcConfig extends WebMvcConfigurationSupport {
  3. /**
  4. * 配置静态资源
  5. * @param registry
  6. */
  7. @Override
  8. protected void addResourceHandlers(ResourceHandlerRegistry registry) {
  9. registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
  10. super.addResourceHandlers(registry);
  11. }
  12. }

现在重新启动项目:css文件已经引用成功。

 3.3  ErrorPageConfig 配置错误页面

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description 配置错误页面 403 404 500 适用于 SpringBoot 2.x
  5. */
  6. @Configuration
  7. public class ErrorPageConfig {
  8. @Bean
  9. public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
  10. WebServerFactoryCustomizer<ConfigurableWebServerFactory> webCustomizer = new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
  11. @Override
  12. public void customize(ConfigurableWebServerFactory factory) {
  13. ErrorPage[] errorPages = new ErrorPage[] {
  14. new ErrorPage(HttpStatus.FORBIDDEN, "/403"),
  15. new ErrorPage(HttpStatus.NOT_FOUND, "/404"),
  16. new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500"),
  17. };
  18. factory.addErrorPages(errorPages);
  19. }
  20. };
  21. return webCustomizer;
  22. }
  23. }

 3.4 MainController 控制器

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description 主控制器
  5. */
  6. @Controller
  7. public class MainController {
  8. private Logger logger = LoggerFactory.getLogger(getClass());
  9. @GetMapping("/login")
  10. public String loginPage(){
  11. System.out.println("login page");
  12. return "login";
  13. }
  14. @GetMapping("/index")
  15. @PreAuthorize("hasAnyRole('USER','ADMIN')")
  16. public String index(){
  17. System.out.println("index page");
  18. return "index";
  19. }
  20. @GetMapping("/admin")
  21. @PreAuthorize("hasAnyRole('ADMIN')")
  22. public String printAdmin(){
  23. System.out.println("hello admin");
  24. return "admin";
  25. }
  26. @GetMapping("/user")
  27. @PreAuthorize("hasAnyRole('USER','ADMIN')")
  28. public String printUser(){
  29. System.out.println("hello user");
  30. return "user";
  31. }
  32. /**
  33. * 找不到页面
  34. */
  35. @GetMapping("/404")
  36. public String notFoundPage() {
  37. return "/error/404";
  38. }
  39. /**
  40. * 未授权
  41. */
  42. @GetMapping("/403")
  43. public String accessError() {
  44. return "/error/403";
  45. }
  46. /**
  47. * 服务器错误
  48. */
  49. @GetMapping("/500")
  50. public String internalError() {
  51. return "/error/500";
  52. }
  53. }

3.5 UserInfoController 用户控制器

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/25
  4. * @Description
  5. */
  6. @Controller
  7. @RequestMapping("/user")
  8. public class UserInfoController {
  9. private Logger logger = LoggerFactory.getLogger(getClass());
  10. @Resource
  11. private UserInfoService userInfoService;
  12. @GetMapping("/getUserInfo")
  13. @ResponseBody
  14. public User getUserInfo(@RequestParam String username){
  15. return userInfoService.getUserInfoByUsername(username);
  16. }
  17. }

SMM框架的其他部分就省略了,非这里重点。

3.6 CustomAccessDecisionManager 自定义权限决策管理器

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/31
  4. * @Description 自定义权限决策管理器
  5. */
  6. @Component
  7. public class CustomAccessDecisionManager implements AccessDecisionManager {
  8. /**
  9. * @Author: qt
  10. * @Description: 取当前用户的权限与这次请求的这个url需要的权限作对比,决定是否放行
  11. * auth 包含了当前的用户信息,包括拥有的权限,即之前UserDetailsService登录时候存储的用户对象
  12. * object 就是FilterInvocation对象,可以得到request等web资源。
  13. * configAttributes 是本次访问需要的权限。即上一步的 MyFilterInvocationSecurityMetadataSource 中查询核对得到的权限列表
  14. **/
  15. @Override
  16. public void decide(Authentication auth, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
  17. Iterator<ConfigAttribute> iterator = collection.iterator();
  18. while (iterator.hasNext()) {
  19. if (auth == null) {
  20. throw new AccessDeniedException("当前访问没有权限");
  21. }
  22. ConfigAttribute ca = iterator.next();
  23. //当前请求需要的权限
  24. String needRole = ca.getAttribute();
  25. if ("ROLE_LOGIN".equals(needRole)) {
  26. if (auth instanceof AnonymousAuthenticationToken) {
  27. throw new BadCredentialsException("未登录");
  28. } else
  29. return;
  30. }
  31. //当前用户所具有的权限
  32. Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
  33. for (GrantedAuthority authority : authorities) {
  34. if (authority.getAuthority().equals(needRole)) {
  35. return;
  36. }
  37. }
  38. }
  39. throw new AccessDeniedException("权限不足!");
  40. }
  41. @Override
  42. public boolean supports(ConfigAttribute configAttribute) {
  43. return true;
  44. }
  45. @Override
  46. public boolean supports(Class<?> aClass) {
  47. return true;
  48. }
  49. }

3.7 CustomLogoutSuccessHandler 注销登录处理

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/31
  4. * @Description 注销登录处理
  5. */
  6. public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
  7. private Logger logger = LoggerFactory.getLogger(getClass());
  8. @Override
  9. public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
  10. System.out.println("注销成功!");
  11. //这里写你登录成功后的逻辑
  12. response.setStatus(HttpStatus.OK.value());
  13. response.setContentType("application/json;charset=UTF-8");
  14. response.getWriter().write("注销成功!");
  15. }
  16. }

3.8 LoginFailureHandler 登录失败处理

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/24
  4. * @Description 登录失败处理
  5. */
  6. @Component("loginFailureHandler")
  7. public class LoginFailureHandler extends SimpleUrlAuthenticationFailureHandler {
  8. private Logger logger = LoggerFactory.getLogger(getClass());
  9. @Resource
  10. private ObjectMapper objectMapper;
  11. @Override
  12. public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
  13. logger.info("登录失败");
  14. this.saveException(request, exception);
  15. this.getRedirectStrategy().sendRedirect(request, response, "/login?error=true");
  16. }
  17. }

 3.9 LoginSuccessHandler 登录成功处理

  1. /** @Author qt
    * @Date 2021/3/24
  2. * @Description 登录成功处理
  3. */
  4. @Component("loginSuccessHandler")
  5. public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
  6. private Logger logger = LoggerFactory.getLogger(getClass());
  7. @Resource
  8. private ObjectMapper objectMapper;
  9. private RequestCache requestCache;
  10. @Override
  11. public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
  12. // 获取前端传到后端的全部参数
  13. Enumeration enu = request.getParameterNames();
  14. while (enu.hasMoreElements()) {
  15. String paraName = (String) enu.nextElement(); System.out.println("参数- " + paraName + " : " + request.getParameter(paraName));
  16. }
  17. logger.info("登录认证成功");
  18. //这里写你登录成功后的逻辑,可以验证其他信息,如验证码等。
  19. response.setContentType("application/json;charset=UTF-8");
  20. JSONObject resultObj = new JSONObject();
  21. resultObj.put("code", HttpStatus.OK.value());
  22. resultObj.put("msg","登录成功");
  23. resultObj.put("authentication",objectMapper.writeValueAsString(authentication));
  24. response.getWriter().write(resultObj.toString());
  25. this.getRedirectStrategy().sendRedirect(request, response, "/index");//重定向
  26. }
  27. }

3.10 login.html 登录页面

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录</title>
  6. <link rel="stylesheet" type="text/css" th:href="@{static/layui/css/layui.css}">
  7. </head>
  8. <body>
  9. <form method="POST" th:action="@{/user/login}">
  10. <div>
  11. 用户名:<input type="text" name="username" id="username">
  12. </div>
  13. <div>
  14. 密码:<input type="password" name="password" id="password">
  15. </div>
  16. <div>
  17. <button type="submit">立即登陆</button>
  18. </div>
  19. <!-- 以下为显示认证失败等提示信息(th:if=""一定要写 )-->
  20. <span style="color: red;" th:if="${param.error}" th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}"></span>
  21. </form>
  22. </body>
  23. </html>

 3.11 效果图片

登录失败

 

 登录成功

 4、自定义ajax请求认证登录

本人比较喜欢使用ajax的登录认证方式,这个比较灵活。

   4.1 目录

   4.2、较表单登录认证的改变

  LoginFailureHandler 登录失败处理

  1. /**
  2. * @Author qt
  3. * @Date 2021/3/24
  4. * @Description 登录失败处理
  5. */
  6. @Component("loginFailureHandler")
  7. public class LoginFailureHandler extends SimpleUrlAuthenticationFailureHandler {
  8. private Logger logger = LoggerFactory.getLogger(getClass());
  9. @Resource
  10. private ObjectMapper objectMapper;
  11. @Override
  12. public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
  13. logger.info("登录失败");
  14. response.setContentType("application/json;charset=UTF-8");
  15. //这里写你登录失败后的逻辑,可加验证码验证等
  16. String errorInfo = "";
  17. if (exception instanceof BadCredentialsException ||
  18. exception instanceof UsernameNotFoundException) {
  19. errorInfo = "账户名或者密码输入错误!";
  20. } else if (exception instanceof LockedException) {
  21. errorInfo = "账户被锁定,请联系管理员!";
  22. } else if (exception instanceof CredentialsExpiredException) {
  23. errorInfo = "密码过期,请联系管理员!";
  24. } else if (exception instanceof AccountExpiredException) {
  25. errorInfo = "账户过期,请联系管理员!";
  26. } else if (exception instanceof DisabledException) {
  27. errorInfo = "账户被禁用,请联系管理员!";
  28. } else {
  29. errorInfo = "登录失败!";
  30. }
  31. logger.info("登录失败原因:" + errorInfo);
  32. //ajax请求认证方式
  33. JSONObject resultObj = new JSONObject();
  34. resultObj.put("code", HttpStatus.UNAUTHORIZED.value());
  35. resultObj.put("msg",errorInfo);
  36. resultObj.put("exception",objectMapper.writeValueAsString(exception));
  37. response.getWriter().write(resultObj.toString());
  38. //表单认证方式
  39. //this.saveException(request, exception);
  40. //this.getRedirectStrategy().sendRedirect(request, response, "/login?error=true");
  41. }
  42. }
  1. LoginSuccessHandler 登录成功处理
  1. /**
  2. * @Author qt
  3. * @Date 2021/3/24
  4. * @Description 登录成功处理
  5. */
  6. @Component("loginSuccessHandler")
  7. public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
  8. private Logger logger = LoggerFactory.getLogger(getClass());
  9. @Resource
  10. private ObjectMapper objectMapper;
  11. @Override
  12. public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
  13. response.setContentType("application/json;charset=UTF-8");
  14. // 获取前端传到后端的全部参数
  15. Enumeration enu = request.getParameterNames();
  16. while (enu.hasMoreElements()) {
  17. String paraName = (String) enu.nextElement(); System.out.println("参数- " + paraName + " : " + request.getParameter(paraName));
  18. }
  19. logger.info("登录认证成功");
  20. //这里写你登录成功后的逻辑,可加验证码验证等
  21. //ajax请求认证方式
  22. JSONObject resultObj = new JSONObject();
  23. resultObj.put("code", HttpStatus.OK.value());
  24. resultObj.put("msg","登录成功");
  25. resultObj.put("authentication",objectMapper.writeValueAsString(authentication));
  26. response.getWriter().write(resultObj.toString());
  27. //表单认证方式
  28. //this.getRedirectStrategy().sendRedirect(request, response, "/index");//重定向
  29. }
  30. }

login.html 登录页面

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录</title>
  6. <link rel="stylesheet" type="text/css" th:href="@{static/layui/css/layui.css}">
  7. </head>
  8. <body>
  9. <form method="POST" action="">
  10. <div>
  11. 用户名:<input type="text" name="username" id="username">
  12. </div>
  13. <div>
  14. 密码:<input type="password" name="password" id="password">
  15. </div>
  16. <div>
  17. <input type="button" name="login" id="login" th:value="立即登陆" onclick="mylogin()">
  18. </div>
  19. </form>
  20.  
  21. <script type="text/javascript" charset="utf-8" th:src="@{static/jquery/jquery-3.5.1.min.js}"></script>
  22. <script type="text/javascript" charset="utf-8" th:src="@{static/layui/layui.js}"></script>
  23. <script th:inline="javascript" type="text/javascript">
  24. layui.use(['form','jquery','layedit', 'laydate'], function () {
  25. var $ = layui.jquery,
  26. form = layui.form,
  27. layer = layui.layer;
  28. });
  29. function mylogin() {
  30. var username = $("#username").val();
  31. var password = $("#password").val();
  32. console.log("username:" + username + "password:" + password);
  33. var index = layer.load(1);
  34. $.ajax({
  35. type: "POST",
  36. dataType: "json",
  37. url: "user/login",
  38. data: {
  39. "username": username,
  40. "password": password
  41. //可加验证码参数等,后台登陆处理LoginSuccessHandler中会传入这些参数
  42. },
  43. success: function (data) {
  44. layer.close(index);
  45. console.log("data===>:" + JSON.stringify(data));
  46. if (data.code == 200) { //登录成功
  47. window.location.href = "index";
  48. } else {
  49. layer.msg(data.msg, {
  50. icon: 2,
  51. time: 3000 //2秒关闭(如果不配置,默认是3秒)
  52. });
  53. }
  54. },
  55. error: function () {
  56. layer.close(index);
  57. layer.msg("数据请求异常!", {
  58. icon: 2,
  59. time: 2000 //2秒关闭(如果不配置,默认是3秒)
  60. });
  61. }
  62. });
  63. }
  64. </script>
  65. </body>
  66. </html>

4.3 演示图片

登录失败

 登录成功

 最后添加一个我写的一个小demo,里面也整合了security框架,使用springboot + ssm后端框架 + maven依赖包管理 + thmeleaf模板引擎 + pear-admin-layui前端框架等。

 demo演示地址:http://www.qnto.top/springfashionsys/login

 demo只对数据分析页面做了权限设置,只有admin才可访问。

转载需要加链接哦,整理不易。

总结:实践是检验真理的唯一标准,亲测可用。

 参考链接:

 https://blog.csdn.net/qq_40298902/article/details/106433192

 https://www.e-learn.cn/topic/3143567

 https://blog.csdn.net/qq_20108595/article/details/89647419

 http://www.spring4all.com/article/428

 https://blog.csdn.net/tanleijin/article/details/100698486

 https://blog.csdn.net/zhaoxichen_10/article/details/88713799

 https://blog.csdn.net/hanxiaotongtong/article/details/103095906

 https://www.jb51.net/article/140429.htm

 https://www.jianshu.com/p/29d10ad22531

 https://blog.csdn.net/weixin_39588542/article/details/110507502

 https://blog.csdn.net/sinat_33151213/article/details/89931819

原文链接:http://www.cnblogs.com/qiantao/p/14605154.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号