SpringCloud+Spring Security+OAuth2授权登录(二)

为了美观和更好的用户体验,我们需要修改登录页面和服务端代码,系统默认只会返回用户无法找到UsernameNotFoundException这一错误,自定义的目的就是希望能区分用户未注册还是账号或密码错误。

所以要加入自己的loginFailureHandler

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(daoAuthenticationProvider());
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
        return daoAuthenticationProvider;
    }
    
 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //放行静态资源
                .antMatchers("/login", "/oauth/**", "/check_token").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                //允许form登录
                .formLogin()
                .loginPage("/login").permitAll()
                //配置登录成功、失败Handler返回自定义错误信息
                .successHandler(loginSuccessHandler)
                .failureHandler(loginFailureHandler)
                .and().logout().permitAll()
                .and().csrf().disable();
    }
@Component
public class LoginFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    /**
     * 拦截 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 错误类型
     */
    @Override
    public void onAuthenticationFailure
            (HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        /* 默认:执行重定向或转发到defaultfailureurl(如果设置),Otherw返回401错误代码 */
        //super.onAuthenticationFailure(request,response,exception)
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        PrintWriter writer = response.getWriter();
        JSONObject res = new JSONObject();
        res.put("code", 401);
        if (exception instanceof UsernameNotFoundException) {
            res.put("msg", "用户不存在");
            writer.write(res.toJSONString());
        }

        if (exception instanceof BadCredentialsException) {
            res.put("msg", "用户名或密码错误");
            writer.write(res.toJSONString());
        }
        writer.flush();
        writer.close();
    }
}

登录页请求

let formData = new FormData();
	//参数
	formData.append("username", this.username);
	formData.append("password", this.password);
	axios.post("/login", formData)
		.then(res => {
		if (401 === res.data.code) {
			alert(res.data.msg);
		} else if (200 === res.data.code) {
			window.location.href = res.data.targetUrl;
		}
	}).catch(error => {
		alert("系统错误");
	});

另外,登录成功后原来的代码采用的是重定向的方式返回的,但是如果我们前端用ajax去请求,重定向的时候就会报错,所以我们还需要改造LoginSuccessHandler

@Component
public class LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    private RequestCache requestCache = new HttpSessionRequestCache();

    @Override
    public void onAuthenticationSuccess
            (HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        SavedRequest savedRequest = requestCache.getRequest(request, response);
        if (savedRequest == null) {
            //直接输入 http://www.avanty.com:8766/login 不带重定向的地址 则可以考虑跳转到本系统的首页 或者自定义提示信息
            return;
        }
        //清除属性
        clearAuthenticationAttributes(request);
        // Use the DefaultSavedRequest URL
        String targetUrl = savedRequest.getRedirectUrl();
        response.setStatus(HttpServletResponse.SC_OK);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        PrintWriter writer = response.getWriter();
        JSONObject res = new JSONObject();
        res.put("code", 200);
        res.put("msg", "认证成功");
        res.put("targetUrl", targetUrl);
        writer.write(res.toJSONString());
        writer.flush();
        writer.close();
    }

    public void setRequestCache(RequestCache requestCache) {
        this.requestCache = requestCache;
    }
}

服务端只返回重定向的地址,由前端自己去跳转


至此,认证服务端差不多就改造完毕了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值