SpringSecurity - 登录注册加密/登录拦截/失败信息回显详解(慢步骤解析)

配置文件中form-login标签详解

login-page                           // 自定义登录页面的url,例如login.html
login-processing-url             // 登录请求拦截的url,即form表单提交的url,默认值是/login

// 以下2个需要配合使用,如果需要认证成功跳转的url,则always-use-default-target需要设置为true
// 如果使用authentication-success-handler-ref处理认证成功,则以下两个属性失效
default-target-url                  // 默认登录成功后跳转的url
always-use-default-target    // 是否总是使用默认登录成功后的url,即default-target-url,默认为false

authentication-failure-url      // 登录失败跳转的url
username-parameter           // 用户名的请求字段,即form表单里用户名的name属性,默认值为username
password-parameter            // 密码的请求字段,即form表单里密码的name属性,默认值为password

// 以下1个不能和default-target-ur、always-use-default-target同时使用,会覆盖这两个
authentication-success-handler-ref        // 指向一个AuthenticationSuccessHandlerImpl处理认证成功的bean

// 以下是不太常用的(就我个人而言),所以不是很了解
authentication-failure-handler-ref              // 指向一个AuthenticationFailureHandlerImpl处理认证失败的bean
authentication-details-source-ref              // 指向一个AuthenticationDetailsSourceImpl,在认证过滤器中和私用
authentication-success-forward-url          // 用于authentication-success-handler-ref
authentication-failure-forward-url             // 用于authentication-failure-handler-ref

登录

一、配置Spring-Security.xml文件(基础配置)

本文讲解是通过我正在写的项目(Dubbo+Zookeeper)来讲解的,都有详细解释。




    
    
    
    
    

    
    
    
    
    

    
    
        
        

        
        

        
        

        
        
            
        

        
        
    

    
    
        
        
            
                
                
            
        
    

二、配置web.xml(SpringSecurity相关)


    
        contextConfigLocation
        classpath:spring/spring-security.xml
    
    
        
            org.springframework.web.context.ContextLoaderListener
        
    

    
        springSecurityFilterChain
        org.springframework.web.filter.DelegatingFilterProxy
    
    
        springSecurityFilterChain
        /*
    

三、更改用户名和密码校验方式(配置文件中写死了,实际我们需要从数据库中获取获取)

1.修改Spring-Security.xml文件,配置一个自定义认证信息bean


    
    
        
    

2.创建UserDetailServiceImpl实现UserDetailService接口

public class UserDetailServiceImpl implements UserDetailsService {
    // 通过bean的方式注入进来
    private SellerService sellerService;

    public void setSellerService(SellerService sellerService) {
        this.sellerService = sellerService;
    }

    /**
     * 登录时自动调用
     * @param username 用户名
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 定义权限的集合 - 全部存的是权限
        List authorityList = new ArrayList<>();
        // 添加用户拥有的角色 - 可以从数据库中读取
        authorityList.add(new SimpleGrantedAuthority("ROLE_SELLER"));
        // 判断用户名是否为空,如果为空直接返回null
        if(username == null){
            return null;
        }
        // 在数据库中去查对象
        Seller seller = sellerService.findById(username);
        // 参数:用户名、密码、权限集合  密码前拼接{noop} 表示不加密
        User user = new User(username,seller.getPassword(),authorityList);
        return user;
    }
}

3.在认证权限管理器中指定加密工具类(注入加密工具类、指定加密工具类)


 
    
        
        
           
            
        
    

上诉代码解释:

这里因为在springMVC.xml中配置了包扫描地址为Controller包,而UserDetailService不在Controller包下,所以没办法通过@Reference注入sellerService(因为是Dubbo项目,这里读者如果不是Dubbo项目,即可以通过@Autowired注入时,就不用通过这种方式来注入,请直接忽略下面的解释)。

:如果是Dubbo项目,还得通过dubbo:reference把sellerService接口服务bean注入进来,如下:

SpringSecurity - 登录注册加密/登录拦截/失败信息回显详解(慢步骤解析)_第1张图片

 

注册 

在对应的Controller类注入PasswordEncoder,通过它的encode方法对明文密码进行加密。

@Autowired
private PasswordEncoder passwordEncoder;

 @RequestMapping("/add")
    public Result add(@RequestBody Seller seller){
        // 获取明文密码
        String password = seller.getPassword();
        // 对明文密码进行加密
        String securityPassword = passwordEncoder.encode(password);
        // 把加密后的密码存储到seller中
        seller.setPassword(securityPassword);
        Result result = sellerService.add(seller);
        return result;
    }

 

登录成功拦截

一、配置拦截器(前提Maven中已经依赖servlet-api),即修改form-login


二、在loginHandler中可以做一些跳转之前的操作,最后再进行跳转(请求转发、重定向)

1.创建拦截器

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
       
    }
}

2.重定向的方式(sendRedirect)

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        System.out.println("登陆成功");
        // 手动跳转
        httpServletResponse.sendRedirect("/admin/index.html");
    }
}

3.请求转发的方式(forward),与重定向一样,在方法里写请求转发的代码即可

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        System.out.println("登陆成功");
        // 手动跳转
        httpServletRequest.getRequestDispatcher("/admin/index.html")
                .forward(httpServletRequest,httpServletResponse);
    }
}

:如果你请求转发的页面含有iframe嵌套页面,则还需要在嵌套页面写入详细的url,如下图

 

登录失败信息回显

一、方法一(开发中一般不这么用,所以简述一下)

1.修改Spring-Security.xml配置文件


    

2.创建拦截器AuthenticationFailureHandlerImpl,实现AuthenticationFailureHandler接口

3.根据异常信息,判断认证异常还是用户名异常。然后写到session中,前端发送请求从session中取出信息

二、方法二(开发中常用),通过地址栏参数来回显信息,但无法知道具体是什么原因导致认证失败

1.修改Spring-Security.xml配置文件,在失败url后加一个参数

2.前端通过JS获取参数进行判断和回显,如果地址栏有error参数,那么就是失败了

// 获取地址栏中的name参数
    function getUrlParam(name) {
        return decodeURIComponent(
            (new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ""])[1].replace(/\+/g, '%20')) || null
    }
// 检查有没有获取到
    function checkError() {
        let res = getUrlParam("error");
        if (res != null) {	// 获取到了error
            // 可以找个标签给他安排上
            console.log("登录失败,原因可能是:未通过审核、审核中、账户已被关闭、账号或密码错误!");
            // 修改地址栏
            window.history.pushState(null, null, "http://localhost:8083/shoplogin.html");
            // 回显信息
            $("#error").text("登录失败,原因可能是:未通过审核、审核中、账户已被关闭、账号或密码错误!");
        }
    }

4.每次进入这个页面就调用一次checkError方法即可

你可能感兴趣的:(安全框架)