SpringBoot集成SpringSecurity(四)前后端分离、Session会话控制

前后端分离

主要实现避免后端控制页面跳转,后端通过返回json让前端控制页面跳转。

自定义登录成功Handler

之前代码中通过defaultSuccessUrl("/index")配置当登录成功后默认跳转到/index,不满足彻底的前后端分离。

我们可以用successHandler(myLoginSuccessHandler)添加登录成功处理器,当用户登录成功后处理并返回给前端json对象,因此无需配置defaultSuccessUrl("/index")。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
​
    @Autowired
    public PasswordEncoder p;
    @Autowired
    public UserDetailsServiceImpl userDetailsServiceImpl;
    @Autowired
    public MyLoginSuccessHandler myLoginSuccessHandler;
​
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServiceImpl)
                .passwordEncoder(p);
    }
​
    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
​
        //拦截并认证所有的请求
        http.authorizeRequests()
                //对于登录接口或登录页面不拦截
                .antMatchers("/login","/mlogin.html").permitAll()
                //对于接口访问必须需要某角色
                .antMatchers("/role").hasRole("ROLE")
                //对于接口访问必须需要某权限
                .antMatchers("/perm").hasAuthority("p1")
                //所有的请求必须经过认证(包括登录),除非加入上面的不拦截
                .anyRequest().authenticated()
                //再返回一个HttpSecurity http
                .and()
                //设置登录页面
                .formLogin().loginPage("/mlogin.html")
                //登录页面填写完成后的提交地址,默认是/login(SpringSecurity已经默认实现了此接口)
                .loginProcessingUrl("/login")
                //登录页面form表单中用户名框对应的name
                .usernameParameter("username")
                //登录页面form表单中密码框对应的name
                .passwordParameter("password")
                //登录成功处理器
                .successHandler(myLoginSuccessHandler).permitAll()
                //登录失败后访问
                .failureUrl("/loginerror");
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }
}

实现AuthenticationSuccessHandler的MyLoginSuccessHandler。ObjectMapper为springboot提供的一个将对象转换为json字符串的类,实际开发过程中可以采用其他json处理插件。

@Component
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", "400");
        map.put("message", "登录成功!" + authentication.getName() + " : " + authentication.getAuthorities());
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}

此时,当登录成功后调用MyLoginSuccessHandler并在前端返回json字符串结果,可通过authentication获取登录用户具体信息。

{ "message": "登录成功!admin:[ROLE_ROLE]"}

自定义登录失败Handler

类似successHandler同样有失败处理器failureHandler,在用户失败处理器中可以处理抛出的异常,功能同failureUrl("/loginerror"),因此无需配置failureUrl("/loginerror")。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
​
    @Autowired
    public PasswordEncoder p;
    @Autowired
    public UserDetailsServiceImpl userDetailsServiceImpl;
    @Autowired
    public MyLoginSuccessHandler myLoginSuccessHandler;
    @Autowired
    public MyLoginFailureHandler myLoginFailureHandler;
​
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServiceImpl)
                .passwordEncoder(p);
    }
​
    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
​
        //拦截并认证所有的请求
        http.authorizeRequests()
                //对于登录接口或登录页面不拦截
                .antMatchers("/login","/mlogin.html","/mmlo","/mlogin").permitAll()
                //对于接口访问必须需要某角色
                .antMatchers("/role").hasRole("ROLE")
                //对于接口访问必须需要某权限
                .antMatchers("/perm").hasAuthority("p1")
                //所有的请求必须经过认证(包括登录),除非加入上面的不拦截
                .anyRequest().authenticated()
                //再返回一个HttpSecurity http
                .and()
                //设置登录页面
                .formLogin().loginPage("/mlogin.html")
                //登录页面填写完成后的提交地址,默认是/login(SpringSecurity已经默认实现了此接口)
                .loginProcessingUrl("/login")
                //登录页面form表单中用户名框对应的name
                .usernameParameter("username")
                //登录页面form表单中密码框对应的name
                .passwordParameter("password")
                //登录成功处理器
                .successHandler(myLoginSuccessHandler).permitAll()
                //登录失败处理器
                .failureHandler(myLoginFailureHandler);
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }
}

实现AuthenticationFailureHandler的MyLoginFailureHandler。在里面可以通过AuthenticationException对异常进行处理。

@Component
public class MyLoginFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        HashMap<String, Object> map = new HashMap<>();
        String a = "";
        if(e instanceof BadCredentialsException) {
            a = "密码错误";
        } else if(e instanceof DisabledException) {
            a = "账户被禁用";
        } else if(e instanceof AccountExpiredException) {
            a = "账户已过期";
        } else if(e instanceof LockedException) {
            a = "账户被锁定";
        } else if(e instanceof CredentialsExpiredException) {
            a = "账户凭证过期";
        } else if(e instanceof UsernameNotFoundException) {
            //在springsecurity中UsernameNotFoundException被屏蔽无法使用,用户找不到会抛BadCredentialsException
            a = "账户不存在";
        } else {
            a = "未知错误";
        }
        System.out.println(e.getMessage());
        map.put("code", "401");
        map.put("message", "登录失败! " + a);
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}

此时,当登录失败后调用MyLoginFailureHandler并在前端返回json字符串结果,如密码错误。

{"message": "登录失败! 密码错误"}

用户未登录处理器

之前的代码中,loginPage("/mlogin.html")来指定未登录用户访问资源时,自动跳转到登录页面,如果不配置loginPage那么会自动跳转到SpringSecurity默认的登陆页面。

在前后端分离时,不使用loginPage设定页面跳转,可以用AuthenticationEntryPoint自定义处理器,当用户未登录访问受限资源时进行处理,无需配置oginPage("/mlogin.html")。

@Override
    protected void configure(HttpSecurity http) throws Exception {
​
        //拦截并认证所有的请求
        http.authorizeRequests()
                //对于登录接口或登录页面不拦截
                .antMatchers("/login").permitAll()
                //对于接口访问必须需要某角色
                .antMatchers("/role").hasRole("ROLE")
                //对于接口访问必须需要某权限
                .antMatchers("/perm").hasAuthority("p1")
                //所有的请求必须经过认证(包括登录),除非加入上面的不拦截
                .anyRequest().authenticated()
                //再返回一个HttpSecurity http
                .and()
                //设置登录页面
                .formLogin()
                //.loginPage("/mlogin.html")
                //登录页面填写完成后的提交地址,默认是/login(SpringSecurity已经默认实现了此接口)
                .loginProcessingUrl("/login")
                //登录页面form表单中用户名框对应的name
                .usernameParameter("username")
                //登录页面form表单中密码框对应的name
                .passwordParameter("password")
                .successHandler(myLoginSuccessHandler).permitAll()
                .failureHandler(myLoginFailureHandler)
                //用户未登录处理器
        .and().exceptionHandling().authenticationEntryPoint(myAuthExceptionEntryPoint);
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }

自定义MyAuthExceptionEntryPoint实现AuthenticationEntryPoint,当用户未登录访问受限资源时提示未登录。

//匿名用户访问无权限的异常
@Component
public class MyAuthExceptionEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", "420");
        map.put("message", "用户未登录");
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}

已登录用户但权限不足处理器

之前的代码中,已登录用户访问受限的资源,此时会抛出默认的一个无权限页面(类似403 Forbidden)。

通过配置accessDeniedHandler(myAccessDeniedHandler)权限不足处理器,当登录用户权限不足时提示权限不足。

@Override
    protected void configure(HttpSecurity http) throws Exception {
​
        //拦截并认证所有的请求
        http.authorizeRequests()
                //对于登录接口或登录页面不拦截
                .antMatchers("/login","/mlogin.html","/mmlo","/mlogin").permitAll()
                //对于接口访问必须需要某角色
                .antMatchers("/role").hasRole("ROLE")
                //对于接口访问必须需要某权限
                .antMatchers("/perm").hasAuthority("p1")
                //所有的请求必须经过认证(包括登录),除非加入上面的不拦截
                .anyRequest().authenticated()
                //再返回一个HttpSecurity http
                .and()
                //设置登录页面
                .formLogin()
                .loginPage("/mlogin.html")
                //登录页面填写完成后的提交地址,默认是/login(SpringSecurity已经默认实现了此接口)
                .loginProcessingUrl("/login")
                //登录页面form表单中用户名框对应的name
                .usernameParameter("username")
                //登录页面form表单中密码框对应的name
                .passwordParameter("password")
                .successHandler(myLoginSuccessHandler).permitAll()
                .failureHandler(myLoginFailureHandler)
                //匿名用户访问资源时无权限处理器
           .and().exceptionHandling().authenticationEntryPoint(myAuthExceptionEntryPoint)
                //已登录用户权限不足处理器
                .accessDeniedHandler(myAccessDeniedHandler);
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }

自定义MyAccessDeniedHandler实现AccessDeniedHandler。

//已登录用户但权限处理器
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", "430");
        map.put("message", "用户无权限");
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}

测试后,未登录用户访问受限资源后提示420错误,已登录用户访问无权资源提示430错误。

用户退出处理器

SpringSecurity中默认的用户退出接口为/logout,在前后端分离时我们自定义用户退出处理器并且可与实际业务进行关联。

用户退出的过程一般是,当前session失效,删除当前用户的RememberMe功能信息,清除当前的SecurityContext,删除cookie,最后重定向到登录页面(如loginPage配置)。

通过配置logout()设置该处理器。

@Override
    protected void configure(HttpSecurity http) throws Exception {
​
        //拦截并认证所有的请求
        http.authorizeRequests()
                //对于登录接口或登录页面不拦截
                .antMatchers("/login","/mlogin.html","/mmlo","/mlogin").permitAll()
                //对于接口访问必须需要某角色
                .antMatchers("/role").hasRole("ROLE")
                //对于接口访问必须需要某权限
                .antMatchers("/perm").hasAuthority("p1")
                //所有的请求必须经过认证(包括登录),除非加入上面的不拦截
                .anyRequest().authenticated()
                //再返回一个HttpSecurity http设置退出登录,退出登录默认地址为/logout
                .and().logout().permitAll()
                //添加退出操作和退出成功操作
                .addLogoutHandler(myLogoutHandler).logoutSuccessHandler(myLogoutSuccessHandler)
                //删除cookie
                .deleteCookies("JSESSIONID")
                //再返回一个HttpSecurity http设置登录,登录默认地址为/login
                .and().formLogin()
                //.loginPage("/mlogin.html")
                //登录页面填写完成后的提交地址,默认是/login(SpringSecurity已经默认实现了此接口)
                .loginProcessingUrl("/login")
                //登录页面form表单中用户名框对应的name
                .usernameParameter("username")
                //登录页面form表单中密码框对应的name
                .passwordParameter("password")
                .successHandler(myLoginSuccessHandler).permitAll()
                .failureHandler(myLoginFailureHandler)
                //匿名用户访问资源时无权限处理器                .and().exceptionHandling().authenticationEntryPoint(myAuthExceptionEntryPoint)
                //已登录用户权限不足处理器
                .accessDeniedHandler(myAccessDeniedHandler);
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }

注销操作处理器、注销成功处理器

//注销操作
@Component
public class MyLogoutHandler implements LogoutHandler {
    @Override
    public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
        //或User user = (User) authentication.getPrincipal()拿到User对象
        String name = authentication.getName();
        System.out.println("用户登出" + name);
        //authentication变量中获取当前用户信息。可以通过这个来实现具体想要的业务,比如记录用户下线退出时间、IP等等。
        SecurityContextHolder.clearContext();
    }
}
//注销成功处理器
@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        User user = (User) authentication.getPrincipal();
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", "480");
        map.put("message", "用户退出成功" + user.getUsername());
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}

测试后,访问/logout,成功退出并清空cookie,提示480代码。实际上可以不配置MyLogoutHandler,只需要MyLogoutSuccessHandler即可。

Session会话控制

Session创建

用户登录成功后,信息保存在服务器Session中。SpringSecurity提供了4种方式控制会话创建。

  • always:如果一个会话尚不存在,将始终创建一个会话。

  • ifRequired:仅在需要时创建会话,默认

  • never:框架永远不会创建会话本身,但如果它已经存在,它将使用一个。

  • stateless:不会创建或使用任何会话,完全无状态。

在configure中进行会话管理,通过sessionManagement()配置。

@Override
    protected void configure(HttpSecurity http) throws Exception {
​
        //拦截并认证所有的请求
        http.authorizeRequests()
          ...省略代码
              .and().sessionManagement()
              .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
              ;
          ...省略代码
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }

如上面代码设定sessionCreationPolicy(SessionCreationPolicy.STATELESS),那么即使登录成功,访问接口仍然提示未登录,因为没有创建使用session。

实际开发中为默认sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)即可,或省略不写。

Session超时管理

在springboot中有2种配置设置超时方式。默认单位都是秒,除非显式写上单位,如server.servlet.session.timeout=60m那么为60分钟。

  • server.servlet.session.timeout=60:在springboot应用程序层控制session的有效时长。
  • spring.session.timeout=60:启用springsession来控制会话。此时server.servlet.session.timeout不起作用。如果是多节点共享session(比如springsession常用的是redis)那么有效解决session持久化和共享的问题。

以上两个是容器的超时时间,配置spring-session-reids中的超时时间可通过@EnableRedisHttpSession注解中的maxInactiveIntervalInSeconds=60配置(默认单位是秒)。【注意:容器超时或重启,但如果配置了redis中没超时,这样仍不需要重新登录。】

如果设定的时间小于1分钟,那么仍按照1分钟处理(即超时最短时间为1分钟)。

session无效/登录超时/session不存在的处理器

session无效/登录超时/session不存在的处理器,通过invalidSessionStrategy(myInvalidSessionStrategy)设置。

@Override
    protected void configure(HttpSecurity http) throws Exception {

        //拦截并认证所有的请求
        http.authorizeRequests()
                ...省略代码
                //session无效或超时处理器
                .invalidSessionStrategy(myInvalidSessionStrategy)
                ...省略代码
                ;
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }

自定义类实现InvalidSessionStrategy。

//session无效/登录超时/session不存在的处理器
@Component
public class MyInvalidSessionStrategy implements InvalidSessionStrategy {
    @Override
    public void onInvalidSessionDetected(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
​
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", "600");
        map.put("message", "长时间无操作,请重新登录");
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}

为了测试方便,设置session超时为60秒。

server.servlet.session.timeout=60

登录成功访问某接口后,无操作60秒后,提示长时间无操作,请重新登录。

注意:invalidSessionStrategy与用户未登录处理器AuthenticationEntryPoint功能类似,经测试发现对antMatchers.permitAll的配置仍然全部拦截,因此不建议设置invalidSessionStrategy,使用用户未登录处理器AuthenticationEntryPoint即可。以后有时间再验证下。

并发登录处理

限制同一用户在不同设备上的并发登录数量,超出数量后仍能登录但是会强迫之前登录设备下线。

maximumSessions设置为1,maxSessionsPreventsLogin设置为false。

限制同一用户在不同设备上的并发登录数量,超出数量后禁止新的设备登录。

maximumSessions设置为1,maxSessionsPreventsLogin设置为true。

即maximumSessions表示同一用户最大并行登录数量,maxSessionsPreventsLogin表示达到最大并行数量后,true为禁止新的登录,false为挤掉已有登录。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
​
    @Autowired
    public PasswordEncoder p;
    @Autowired
    public UserDetailsServiceImpl userDetailsServiceImpl;
    @Autowired
    public MyLoginSuccessHandler myLoginSuccessHandler;
    @Autowired
    public MyLoginFailureHandler myLoginFailureHandler;
    @Autowired
    public MyAuthExceptionEntryPoint myAuthExceptionEntryPoint;
    @Autowired
    public MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    public MyLogoutHandler myLogoutHandler;
    @Autowired
    public MyLogoutSuccessHandler myLogoutSuccessHandler;
    @Autowired
    public MyInvalidSessionStrategy myInvalidSessionStrategy;
    @Autowired
    public MySessionInformationExpiredStrategy mySessionInformationExpiredStrategy;
​
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServiceImpl)
                .passwordEncoder(p);
    }
​
    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
​
        //拦截并认证所有的请求
        http.authorizeRequests()
        ...省略代码
                .and().sessionManagement()         .maximumSessions(1).maxSessionsPreventsLogin(false).expiredSessionStrategy(mySessionInformationExpiredStrategy);
        ...省略代码
        //开启跨域访问
        http.cors().disable();
        //关闭跨域攻击
        http.csrf().disable();
    }
}

自定义类SessionInformationExpiredStrategy实现SessionInformationExpiredStrategy。

//session失效/超出同账户并发登录数策略
@Component
public class MySessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {
    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent sessionInformationExpiredEvent) throws IOException, ServletException {
        HashMap<String, Object> map = new HashMap<>();
        map.put("code", "610");
        map.put("message", "您已在其他设备登录,请重新登录");
        HttpServletResponse httpServletResponse = sessionInformationExpiredEvent.getResponse();
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}

测试:

  1. 当maximumSessions(1).maxSessionsPreventsLogin(false):设备A登录后,访问/index正常;使用其他设备B登录后,设备A访问/index会提示"您已在其他设备登录,请重新登录"。

  2. 当maximumSessions(1).maxSessionsPreventsLogin(true):设备A登录后,访问/index正常;使用其他设备B登录后会提示未知错误。原因是在自定义登录失败Handler(MyLoginFailureHandler)中并没有捕获SessionAuthenticationException(Maximum sessions of 1 for this principal exceeded)。因此可以添加对这个异常的捕获。采用如下代码块后,超过用户数后会提示禁止登录。

else if(e instanceof SessionAuthenticationException && e.getMessage().startsWith("Maximum sessions")){
    a = "您已在其他设备登录,禁止登录";
}

 

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Spring Security是一个强大的安全框架,可以在Spring Boot应用程序中使用。Spring Boot可以轻松地集成Spring Security,为应用程序提供认证和授权的功能。 要集成Spring Security,需要完成以下步骤: 1.添加Spring Security依赖项:在pom.xml文件中添加Spring Security依赖项。 2.配置Spring Security:创建一个Security配置类,并在其中定义安全规则。 3.启用Spring Security:在应用程序的启动类中使用@EnableWebSecurity注释启用Spring Security。 通过这些步骤,您可以为Spring Boot应用程序添加安全性,并保护它免受未经授权的访问。 ### 回答2: Spring Boot是一个相当流行的Java框架,它能够极大地简化Java开发者的工作,并且支持大量的集成,其中包括集成Spring SecuritySpring Security是一个强大的框架,用于保护Web应用程序的安全性。在本文中,我们将讨论Spring BootSpring Security集成。 一、集成Spring Security依赖 要集成Spring Security,我们需要在我们的Spring Boot应用程序中添加Spring Security的依赖项。我们可以使用 Maven 或 Gradle 来管理我们的项目依赖关系。 在下面的示例中,我们将使用Maven。在pom.xml文件中,添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 二、配置Spring Security 完成依赖注入后,我们需要配置Spring Security,以确保我们的应用程序与身份验证和授权有关的所有部分都按照预期进行工作。 我们可以通过创建一个配置类来完成此操作。 首先,我们需要创建一个@Configuration注释的类,并使用@EnableWebSecurity注释进行注释。 然后,我们可以扩展WebSecurityConfigurerAdapter类,并覆盖configure方法。 ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { // security配置具体实现 @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .and() .httpBasic(); } } ``` 在上面的示例中,我们创建了一个名为SecurityConfig的类,并使用@EnableWebSecurity注释进行注释。我们还覆盖了WebSecurityConfigurerAdapter的configure方法,并定义了我们的HTTP安全配置。 在此示例中,我们允许任何请求进行身份验证,并定义了基本身份验证。 三、添加用户和角色 我们已经定义了我们的安全配置,但还没有定义任何用户和角色。我们可以通过使用 @Configuration注释和@ConfigurationProperties注释来添加用户和角色。 我们可以先定义一个自定义属性的Java类,如下: ``` @ConfigurationProperties(prefix = "myapp") public class SecurityProperties { private String username; private String password; private String role; // getter和setter方法 } ``` 然后,在我们的配置类中,我们可以使用 Java Config 的方式将其注入到类中: ``` @Configuration @EnableWebSecurity @EnableConfigurationProperties(SecurityProperties.class) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SecurityProperties securityProperties // security配置具体实现 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser(securityProperties.getUsername()) .password("{noop}" + securityProperties.getPassword()) .roles(securityProperties.getRole()); } } ``` 上面的示例中,我们首先使用@EnableConfigurationProperties注释了SecurityProperties类,并将其自动注入到我们的配置类中。然后,我们将使用该类中的属性来创建内存身份验证,然后配置用户名,密码和角色,这将使用我们在配置文件中定义的账号密码。 、使用自定义登录页面 Spring Security提供了默认的登录页面,但如果我们希望使用自己的自定义登录页面,则需要添加一个控制器来处理登录请求,并在配置类中进行设置。 ``` @Controller public class LoginController { @GetMapping("/login") public String getLoginPage() { return "login"; } } @Configuration @EnableWebSecurity @EnableConfigurationProperties(SecurityProperties.class) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SecurityProperties securityProperties // security配置具体实现 @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // 添加需要放过的静态资源 .antMatchers("/", "/home", "/register").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") // 设置自定义登录页面 .permitAll() .and() .httpBasic() .and() .logout() .permitAll(); } } ``` 上面的示例中,我们创建了一个名为LoginController的控制器,用于处理登录请求。 然后,我们在configure方法中定义了需要允许所有用户访问的页面。 最后,我们配置了自定义登录页面,并将其设置为/login。 总结 在这篇文章中,我们讨论了如何集成 Spring SecuritySpring Boot 的应用程序中。 我们首先添加了Spring Security的依赖项,并创建了一个配置类。 然后,我们添加了用户和角色,并定义了如何使用自定义登录页面。 通过完成这些步骤,我们可以确保我们的应用程序安全,并保护客户端免受攻击。 ### 回答3: Spring Boot是一种用于轻松构建Java应用程序的框架,而Spring Security是一个用于保护应用程序的身份验证和授权框架。在这里,我们将讨论如何将Spring Boot集成Spring Security。 首先,我们需要在pom.xml文件中添加Spring Security依赖项: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 接下来,我们需要配置Spring Security。这可以通过创建一个类来完成,并使用@Configuration注释来进行注释。我们还需要扩展WebSecurityConfigurerAdapter类。 ``` @EnableWebSecurity @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/", "/home").permitAll() .antMatchers("/admin").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("user").password("{noop}password").roles("USER") .and() .withUser("admin").password("{noop}password").roles("USER", "ADMIN"); } } ``` 在此示例中,我们启用了Web Security,并配置了以下内容: 1. 除了主页之外的所有页面都需要身份验证 2. 如果用户拥有ADMIN角色,则允许访问/admin页面 3. 禁用跨站点请求伪造(CSRF)保护 4. 配置表单登录和跳转页面 5. 使用内存身份验证管理器配置了两个用户 现在,我们可以通过以下方式测试Spring Security: 1. 启动应用程序 2. 访问http://localhost:8080/login 3. 输入用户名和密码(user/password 或 admin/password) 4. 尝试访问http://localhost:8080/admin 如果用户拥有ADMIN角色,则允许访问/admin页面,否则将显示403错误页面。 总之,Spring Boot集成Spring Security是一种用于保护应用程序的身份验证和授权框架。我们可以轻松地使用Spring Security通过添加依赖项和配置文件来保护我们的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值