SpringBoot + Spring Security 多认证源(钉钉,账密)

源码地址

Spring Security 多认证源

业务需求

1.Springboot +Spring Security权限框架
2.前后端分离返回json数据,而不有后端重定向
3.可使用钉钉登陆(钉钉app企业应用)+账号密码登陆

spring security配置

1.新建WebSecurityConfig配置文件继承WebSecurityConfigurerAdapter,并重写configure的入参为HttpSecurity的方法

http.cors(withDefaults())
                .csrf().disable()
                .authorizeRequests(expressionInterceptUrlRegistry ->
                                expressionInterceptUrlRegistry
                        .anyRequest().authenticated()
                )
                .formLogin().disable()
                .exceptionHandling().
                authenticationEntryPoint(
                (request, response, ex) -> {
                    SpringUtil.writeResponse(response, HttpServletResponse.SC_UNAUTHORIZED, ResultEnum.NO_LOGIN
                            , new HashMap<>(1), "");
                }
        );

2.添加自定义继承自AbstractAuthenticationProcessingFilter的Filter

public class DingTalkAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    protected DingTalkAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(new AntPathRequestMatcher(defaultFilterProcessesUrl, "POST"));
    }

    protected DingTalkAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
        super(requiresAuthenticationRequestMatcher);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
        String code = httpServletRequest.getParameter("code");
        //新建一个AuthenticationToken以便接下来的认证
        PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(null, code);
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(httpServletRequest));
        return this.getAuthenticationManager().authenticate(authRequest);
    }

3.钉钉认证DingTalkAuthenticationProvider

public class DingTalkAuthenticationProvider implements AuthenticationProvider {

    private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String token = authentication.getCredentials().toString();
        OapiUserGetuserinfoResponse userInfo;
        try{
            userInfo = dingTalkUtil.getUserInfo(token);
        }catch (Exception e){
            throw new AuthenticationServiceException(e.getMessage());
        }
        String userid = userInfo.getUserid();
        SysUser sysUser = sysUserService.findSysUserByToken(userid);
        if (null == sysUser) {
            throw new UsernameNotFoundException("钉钉code未绑定:" + userid + ",无法完成认证,请联系管理人员");
        }
        SysUserDetails sysUserDetails = new SysUserDetails();
        BeanUtils.copyProperties(sysUser, sysUserDetails);
        UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(sysUserDetails, authentication.getCredentials(), this.authoritiesMapper.mapAuthorities(sysUserDetails.getAuthorities()));
        result.setDetails(authentication.getDetails());
        return result;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return aClass.equals(PreAuthenticatedAuthenticationToken.class);
    }

4.添加filter到configure方法的HttpSecurity中

 DingTalkAuthenticationFilter filter = new DingTalkAuthenticationFilter("/sys-user/dt-login");
        ProviderManager providerManager =
                new ProviderManager(Collections.singletonList(dingTalkAuthenticationProvider));
        filter.setAuthenticationManager(providerManager);
        filter.setAuthenticationFailureHandler((request, response, ex) -> {
            SpringUtil.writeResponse(response, HttpServletResponse.SC_OK, ResultEnum.LOGIN_ERROR
                    , new HashMap<>(1), ex.getMessage());
        });
        filter.setAuthenticationSuccessHandler((request, response, ex) -> {
            SysUser sysUser = SecurityUtil.getSysUser();
            HashMap<Object, Object> result = new HashMap<>(3);
            result.put("username", sysUser.getUsername());
            result.put("admin", sysUser.getAdmin());
            result.put("department_group_nos", Arrays.asList(sysUser.getDepartmentGroupNo()));
            SpringUtil.writeResponse(response, HttpServletResponse.SC_OK, ResultEnum.SUCCESS
                    , result, "");
        });
        http.addFilterAt(filter, UsernamePasswordAuthenticationFilter.class);

6.用户名密码认证同理

public class LoginAuthenticationFilter  extends AbstractAuthenticationProcessingFilter {

    public LoginAuthenticationFilter(String url) {
        super(new AntPathRequestMatcher("/sys-user/login", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }

        username = username.trim();
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(authRequest);
    }
LoginAuthenticationFilter filter1 = new LoginAuthenticationFilter("/sys-user/login");
        ProviderManager providerManager1 =
                new ProviderManager(Collections.singletonList(authenticationProvider()));
        filter1.setAuthenticationManager(providerManager1);
        filter1.setAuthenticationFailureHandler((request, response, ex) -> {
            SpringUtil.writeResponse(response, HttpServletResponse.SC_OK, ResultEnum.LOGIN_ERROR
                    , new HashMap<>(1), ex.getMessage());
        });
        filter1.setAuthenticationSuccessHandler((request, response, ex) -> {
            SysUser sysUser = SecurityUtil.getSysUser();
            HashMap<Object, Object> result = new HashMap<>(3);
            result.put("username", sysUser.getUsername());
            result.put("admin", sysUser.getAdmin());
            result.put("department_group_nos", Arrays.asList(sysUser.getDepartmentGroupNo()));
            SpringUtil.writeResponse(response, HttpServletResponse.SC_OK, ResultEnum.SUCCESS
                    , result, "");
        });
        http.addFilterAt(filter1, UsernamePasswordAuthenticationFilter.class);

文章只贴出了主要代码,部分业务逻辑需要自己实现,后期将整理代码,并逐一分析实现的思想

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值