SpringSecurity 前后端分离

初学springSecurity时,我们发现它还是高度前后端耦合的,为了能好好改造它,我先分析了它实现的原理:它底层是javaweb中的Filter 而Filter对象有一个dofilter方法 ,这个方法基本和sevelt的doget方法的参数一样都有 httpRequst 对象, 所以它是用的httpRequest对象进行了请求的转发. 把filter匹配的url都转发到Login里面。
所以进行改造的第一步就是改变它的底层逻辑 , 不在是转发,而是用HttpReponse对象返回 json :

package com.itheima._2021_3_2_springboot_security_devide;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.devtools.restart.FailureHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootApplication(scanBasePackages = "com.itheima")
@EnableWebSecurity()
@MapperScan(basePackages = "com.itheima.Dao")
public class Application extends WebSecurityConfigurerAdapter {
    @Value("${system.user.password.secret}")
    private String scret;
    @Bean("passwordEncoder")
    public PasswordEncoder getPasswordEncoder(){
        return new Pbkdf2PasswordEncoder();
    }
    @Autowired
    @Qualifier("passwordEncoder")
    private PasswordEncoder PasswordEncoder;

    @Autowired
    @Qualifier("Service1")
    UserDetailsService userDetailsService;

    @Autowired
    private ObjectMapper objectMapper;

//    @Override
//    public void  configure(AuthenticationManagerBuilder authenticationManagerBuilder)  {
//        PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder(scret);
//
//        try {
//            authenticationManagerBuilder.userDetailsService(userDetailsService)
//                    .passwordEncoder(passwordEncoder);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//
//    }

    @Bean
    public AuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setPasswordEncoder(PasswordEncoder);
        authenticationProvider.setUserDetailsService(userDetailsService);
        return authenticationProvider;
    }


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






        http
                .authenticationProvider(authenticationProvider())
                .httpBasic()
                //未登录时,进行json格式的提示,很喜欢这种写法,不用单独写一个又一个的类
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
                    @Override
                    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        //在这里 可以把我们 覆写的filter写入 //这个filter处理的是未登录的问题
                        httpServletResponse.setContentType("text/html;charset=UTF-8");
                        PrintWriter writer = httpServletResponse.getWriter();
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("code", 403);
                        map.put("message", "未登录");
                        writer.write(objectMapper.writeValueAsString(map));
                        writer.flush();
                        writer.close();
                    }
                })
                //已经登录失败的处理
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()//必须授权了才能范围
                .and()
                .formLogin()
                .permitAll()
                //登录失败 的handler  ,也是返回json而不是转发
                .failureHandler(new AuthenticationFailureHandler() {


                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                        PrintWriter out = httpServletResponse.getWriter();
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("code", 401);
                        if (e instanceof BadCredentialsException) {
                            map.put("message", "用户名或密码错误");
                        } else if (e instanceof DisabledException) {
                            map.put("message", "账户被禁用");
                        } else {
                            map.put("message", "登录失败!");
                        }
                        out.write(objectMapper.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                //登录成功时
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("code", 200);
                        map.put("message", "登录成功");
                        map.put("data", authentication);
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter out = httpServletResponse.getWriter();
                        out.write(objectMapper.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .and()
                .exceptionHandling()
                //当没有权限访问某url时,
                .accessDeniedHandler(new AccessDeniedHandler() {
                    @Override
                    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
                        PrintWriter out = httpServletResponse.getWriter();
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("code", 403);
                        map.put("message", "权限不足");
                        out.write(objectMapper.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .and()
                .logout()

                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("code", 200);
                        map.put("message", "退出成功");
                        map.put("data", authentication);
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter out = httpServletResponse.getWriter();
                        out.write(objectMapper.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                }).permitAll();
        //开启跨域访问
        http.cors().disable();
        //开启模拟请求
        http.csrf().disable(); //其实csrf也可以用前后端分离来实现 ,


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





}


测试:用本地html调用接口试试

<html>
<head>

    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="content-type" content="text/html;charset=utf-8">

</head>

<body>
   <form name='f' action='http://localhost:8080/login' method='POST'>
<table>
	<tr><td>User:</td><td><input type='text' name='username' value=''></td></tr>
	<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
	<tr><td colspan='2'><input name="submit" type="submit" value="Login"/></td></tr>
</table>
</form>

<a href="www.baidu.com">???</a>
</body>
</html>

得到json提示
{“code”:401,“message”:“用户名或密码错误”}

到这里springSecurity的前后分离 也就完成了,总结,传统javawe工程转前后端分离项目基本就是把请求的转发和重定向 ,变成返回json字符串。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值