Spring Security 自定义登陆表单

虽然 Spring Security 提供了默认的登录表单,实际项目里肯定是不可以直接使用的,当然 Spring Security 也提供了自定义登录表单的功能。

spring-security.xml

image.png
    


    
    
        
        
        
        
        
        
    
    
        
            
                
                
            
        
    

Spring Security 允许多个 存在:

上面的配置 ,导致访问 /login 页面时也要经过很多 filter,例如 UsernamePasswordAuthenticationFilter, SecurityContextPersistenceFilter, SessionRepositoryFilter 等,其实不需要登陆就能访问的页面,例如登陆页面, js, css, png 等是不需要经过这些 filter 的,则可以配置 http 的 security 为 none,这样就能提高程序的效率:




LoginController

前一节中,注销是在 LoginController 中使用函数 logoutPage() 来处理的,这一节注销直接在 spring-security.xml 里配置 来实现的,把 logoutPage() 函数从 LoginController 里删除

    
package com.xtuer.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
@Controller
public class LoginController {
    @GetMapping("/login")
    public String loginPage(@RequestParam(value="error", required=false) String error,
                            @RequestParam(value="logout", required=false) String logout,
                            ModelMap model) {
        if (error != null) {
            model.put("error", "Username or password is not correct");
        } else if (logout != null) {
            model.put("logout", "Logout successful");
        }
        return "login.html";
    }
    @RequestMapping("/deny")
    @ResponseBody
    public String denyPage() {
        return "You have no permission to access the page";
    }
}

登陆表单 login.html



    Login Page


    
    
    
Username:
Password:

测试

访问 http://localhost:8080/hello
访问 http://localhost:8080/admin
输入错误的用户名或密码,观察登陆失败的页面
输入正确的用户名和密码 admin/Passw0rd,继续登陆
访问 http://localhost:8080/logout,观察注销成功的页面
访问 http://localhost:8080/admin
输入正确的用户名和密码 alice/Passw0rd,继续登陆
提示权限不够

自定义登陆成功的 handler

设置 authentication-success-handler-ref 为自定义登陆成功的 handler,就可以使用同一个登录表单,登录成功后根据用户的角色或者权限重定向到不同的页面:

    



    
    
    
    
    
     

注意:自定义登录成功的 handler 后 default-target-url 不再起作用。

    
package com.xtuer.security;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        // 用户登录成功后访问不同的页面:
        // 1. 获取用户登录前访问的 URL
        // 2. 如果 url 不为空,访问登录前的页面
        // 3. 如果 url 为空,登录后根据用户的角色访问对应的页面
        SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
        String redirectUrl = (savedRequest == null) ? "" : savedRequest.getRedirectUrl();
        if (!redirectUrl.isEmpty()) {
            response.sendRedirect(redirectUrl);
            return;
        }
        // 获取登录用户信息
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        for (GrantedAuthority authority : auth.getAuthorities()) {
            String role = authority.getAuthority(); // 用户的权限
            // 不同的用户访问不同的页面
            if ("ROLE_ADMIN".equals(role)) {
                redirectUrl = "/admin";
            } else {
                redirectUrl = "/hello";
            }
        }
        response.sendRedirect(redirectUrl);
    }
}

你可能感兴趣的:(Spring Security 自定义登陆表单)