spring security 自定義多種方式登錄授權(普通用戶、管理員、第三方登錄)

1. 自定義token,繼承 AbstractAuthenticationToken

目的:主要用於包裝區別過濾條件。第2步用到。

public class WxLoginAuthenticationToken extends AbstractAuthenticationToken {

    private static final long serialVersionUID = 510L;
    private final Object principal;
    private Object credentials;

    public WxLoginAuthenticationToken(Object principal, Object credentials) {
        super((Collection)null);
        this.principal = principal;
        this.credentials = credentials;
        this.setAuthenticated(false);
    }

    public WxLoginAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }

    public Object getCredentials() {
        return this.credentials;
    }

    public Object getPrincipal() {
        return this.principal;
    }

    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        if (isAuthenticated) {
            throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        } else {
            super.setAuthenticated(false);
        }
    }

    public void eraseCredentials() {
        super.eraseCredentials();
        this.credentials = null;
    }

}

2. 自定義攔截類Filter,繼承 AbstractAuthenticationProcessingFilter

目的:對前端傳輸過來的數據進行包裝,

public class WxLoginFilter extends AbstractAuthenticationProcessingFilter {

    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
    private String usernameParameter = "username";
    private String passwordParameter = "password";
    private boolean postOnly = true;

    public WxLoginFilter() {
        super(new AntPathRequestMatcher("/wx/login", "POST"));
    }


    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {

            HashMap hashMap = JSONObject.parseObject(ReadAsChars(request), HashMap.class);
            String username = (String) hashMap.get("username");
            String password = (String) hashMap.get("password");
            if (username == null) {
                username = "";
            }

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

            username = username.trim();

            // 該處對第一步的token進行包裝
            WxLoginAuthenticationToken authRequest = new WxLoginAuthenticationToken(username, password);

            this.setDetails(request, authRequest);

            return this.getAuthenticationManager().authenticate(authRequest);
        }
    }

    public static String ReadAsChars(HttpServletRequest request)
    {

        BufferedReader br = null;
        StringBuilder sb = new StringBuilder("");
        try
        {
            br = request.getReader();
            String str;
            while ((str = br.readLine()) != null)
            {
                sb.append(str);
            }
            br.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (null != br)
            {
                try
                {
                    br.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(this.passwordParameter);
    }

    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(this.usernameParameter);
    }

    protected void setDetails(HttpServletRequest request, WxLoginAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    public void setUsernameParameter(String usernameParameter) {
        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
        this.usernameParameter = usernameParameter;
    }

    public void setPasswordParameter(String passwordParameter) {
        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
        this.passwordParameter = passwordParameter;
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getUsernameParameter() {
        return this.usernameParameter;
    }

    public final String getPasswordParameter() {
        return this.passwordParameter;
    }
}

3. 實現登錄驗證邏輯

@Slf4j
@Component
public class WxLoginProvider implements AuthenticationProvider {

    @Autowired
    ISysUserService userService;

    @Autowired
    private SysPermissionService permissionService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        log.info("第三方微信登錄");
        String username = (String) authentication.getPrincipal();
        String password = (String) authentication.getCredentials();

		//該處僅供參考,不做登錄邏輯處理。登錄成功後,返回對應的值,返回null則登錄失敗
		
        return null;
    }

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

4. security配置

由於項目原因,僅貼上部分代碼:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
至此,完成自定義(多方式)登錄驗證。多個登錄方式,可添加多個處理.

參考文檔:
https://blog.csdn.net/qq_36521507/article/details/103365805
https://blog.csdn.net/qq_36521507/article/details/103370070

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章