spring security实现多接口登录

1. 新建项目,导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. 启动类

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

3. 在UsernamePasswordAuthenticationFilter中我们可以看到,登录的请求为/login,请求方式为post,同时还看到定义的登录的用户名密码为username, password。这些东西都是可以改的。我们写一个类继承UsernamePasswordAuthenticationFilter,写逻辑覆盖需要修改的东西即可。

public class MyAuthencationFilter extends UsernamePasswordAuthenticationFilter {

    /**
     * 如果不需要json登录方式可以不重写此方法
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //判断是否是JSON登录
        String contentType = request.getContentType();
        if (MediaType.APPLICATION_JSON_UTF8_VALUE.equalsIgnoreCase(contentType)
                || "application/json; charset=UTF-8".equalsIgnoreCase(contentType)
                || MediaType.APPLICATION_JSON_VALUE.equals(contentType)) {

            try {
                //获取提交的JSON数据
                ServletInputStream ris = request.getInputStream();
                StringBuilder content = new StringBuilder();
                byte[] b = new byte[1024];
                int lens;
                while ((lens = ris.read(b)) > 0) {
                    content.append(new String(b, 0, lens));
                }
                //从JSON数据中获取用户名和密码
                JSONObject dataObject = JSONObject.parseObject(content.toString());
                // 这里的username和password也可以自己指定名称,那么登录的时候就用指定的就行了
                UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                        dataObject.getString("username"), dataObject.getString("password"));
                setDetails(request, token);
                return this.getAuthenticationManager().authenticate(token);
            } catch ( IOException e) {
                return super.attemptAuthentication(request, response);
            }
        } else {
            return super.attemptAuthentication(request, response);
        }
    }
}

4.写一个类继承WebSecurityConfigurerAdapter,自定义一些security配置信息。

 

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    // 自定义登录成功处理器,可以处理登录成功时的逻辑,也可不写
    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    // 自定义登录失败处理器,可以处理登录失败时的逻辑,也可不写
    @Autowired
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    // 自定义登出成功处理器,可以处理登出成功时的逻辑,也可不写
    @Autowired
    private MyLogoutSuccessHandler myLogoutSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .logout()
                .logoutSuccessHandler(myLogoutSuccessHandler);

        http.addFilterAt(myAuthencationFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAt(myAuthencationFilter2(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAt(myAuthencationFilter3(), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    MyAuthencationFilter myAuthencationFilter() throws Exception {
        MyAuthencationFilter filter = new MyAuthencationFilter();
        filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
        filter.setFilterProcessesUrl("/login/page1");
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }

    @Bean
    MyAuthencationFilter myAuthencationFilter2() throws Exception {
        MyAuthencationFilter filter = new MyAuthencationFilter();
        filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
        filter.setFilterProcessesUrl("/login/page2");
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }

    @Bean
    MyAuthencationFilter myAuthencationFilter3() throws Exception {
        MyAuthencationFilter filter = new MyAuthencationFilter();
        filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
        filter.setFilterProcessesUrl("/login/page3");
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }
}

5.自定义登录成功处理器,在Authentication对象中会封装用户信息,需要可以使用其getPrincipal()方法获取。

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    private ObjectMapper mapper = new ObjectMapper();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        // 以json格式返回数据
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(mapper.writeValueAsString("登录成功"));
        response.getWriter().close();
    }
}

6.自定义登录失败处理器,实现方法后可以写登录失败的日志等信息,AuthenticationException 中会封装异常信息。

@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private ObjectMapper mapper = new ObjectMapper();

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(mapper.writeValueAsString("登录失败"));
        response.getWriter().close();
    }
}

7.自定义登出成功处理器,这里退出登录时使用json格式返回,也可以自定义一些东西,如输出日志等。

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {

    private ObjectMapper mapper = new ObjectMapper();

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

        // 以json格式返回数据
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(mapper.writeValueAsString("登出成功"));
    }
}

8.定义controller

@RestController
public class SecurityController {

    @GetMapping("/api/fun")
    public String fun() {
        return "hello";
    }
}

9. 访问/api/fun,由于没登录会跳转到登录页面,也可以通过/login/page1登录,以json格式传入参数(默认用户名是user,密码是项目启动时控制台打印的密码),如下:

10. 退出后可以用/login/page2或/login/page3进行登录。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security 是一个功能强大且灵活的安全框架,可以用于在应用程序中实现多表登录。下面是一种常见的实现方式: 1. 创建用户表和角色表:在数据库中创建用户表和角色表,并建立它们之间的关联关系。用户表通常包含用户名、密码和其他相关信息,而角色表则用于定义不同用户角色的权限。 2. 实现用户认证:通过继承 Spring Security 提供的 UserDetailsService 接口并重写其中的方法,来实现自定义的用户认证逻辑。在这个过程中,你可以从多个表中查询用户信息并构建 UserDetails 对象。 3. 配置认证提供者:通过配置 AuthenticationProvider,将自定义的用户认证逻辑与 Spring Security 关联起来。可以使用 DaoAuthenticationProvider 类来处理基于数据库的认证。 4. 配置登录页面:使用 Spring Security 的表单登录功能,配置登录页面,并指定登录页面的 URL、用户名参数、密码参数等相关信息。 5. 配置角色授权:通过配置 WebSecurity,定义不同用户角色的访问权限。你可以使用 @PreAuthorize 或 @Secured 注解来标注需要特定角色才能访问的方法或路径。 6. 配置密码加密:为了保护用户的密码安全,建议使用密码加密算法对密码进行加密。Spring Security 提供了多种加密方式,如 BCrypt、SHA-256 等。你可以通过配置 PasswordEncoder 来指定使用的加密算法。 以上是一个大致的实现流程,具体的代码实现和配置可能会根据你的业务需求和数据库设计有所不同。你可以参考 Spring Security 的官方文档和示例代码来更详细地了解如何实现多表登录

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值