前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security 4 自定义登录表单 注解和XML例子(带源码)

Spring Security 4 自定义登录表单 注解和XML例子(带源码)

作者头像
明明如月学长
发布2021-08-27 15:17:05
8070
发布2021-08-27 15:17:05
举报

上一篇文章: Spring Security 4 Hello World 基于注解 和 XML 例子  下一篇:Spring Security 4 退出 示例

原文地址:http://websystique.com/spring-security/spring-security-4-custom-login-form-annotation-example/

【已翻译文章,点击分类里面的spring security 4查看。】

【 翻译by 明明如月 QQ 605283073】

本文演示Spring Security 4整合Spring MVC web应用的自定义登录表单

在 Spring Security 4 Hello World Annotation+xml 例子中,我们已经看到了如果我们自己不指定登录表单,Spring Security 提供的默认的登录表单。在本文,我们将创建自己的登录表单。

基本思想是,Security Configuration 类中 增加调用formLogin() 的loginPage(URL) 方法

如下:

代码语言:javascript
复制
.and().formLogin().loginPage("/login")

然后,在Spring MVC Controller 中映射“/login” url对应自己写的登录view ,返回登录界面。

这样,如果尝试登录,自定的登录界面将会被显示。其他的登录方法也一样。

下面是针对此方案提供的一个完整的例子

---------------------------------------------------------------------

所用到的技术或者软件:

  • Spring 4.1.6.RELEASE
  • Spring Security 4.0.1.RELEASE
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse JUNO Service Release 2

让我们开始吧。。。

---------------------------------------------------------------------------

第1步: 项目目录结构

下面是最终的项目目录结构

现在我们添加上面结构提到的文件和具体内容。

第2步:更新pom.xml文件添加需要的依赖
代码语言:javascript
复制
    4.0.0
 
    com.websystique.springsecurity
    SpringSecurityCusotmLoginFormAnnotationExample
    1.0.0
    war
 
    SpringSecurityCusotmLoginFormAnnotationExample
 
    
        4.1.6.RELEASE
        4.0.1.RELEASE
    
 
    
        
        
            org.springframework
            spring-core
            ${springframework.version}
        
        
            org.springframework
            spring-web
            ${springframework.version}
        
        
            org.springframework
            spring-webmvc
            ${springframework.version}
        
 
        
        
            org.springframework.security
            spring-security-web
            ${springsecurity.version}
        
        
            org.springframework.security
            spring-security-config
            ${springsecurity.version}
        
 
        
            javax.servlet
            javax.servlet-api
            3.1.0
        
        
            javax.servlet.jsp
            javax.servlet.jsp-api
            2.3.1
        
        
            javax.servlet
            jstl
            1.2
        
    
 
    
        
            
                
                    org.apache.maven.plugins
                    maven-compiler-plugin
                    3.2
                    
                        1.7
                        1.7
                    
                
                
                    org.apache.maven.plugins
                    maven-war-plugin
                    2.4
                    
                        src/main/webapp
                        SpringSecurityCusotmLoginFormAnnotationExample
                        false
                    
                
            
        
        SpringSecurityCusotmLoginFormAnnotationExample
第3步: 添加Spring Security Configuration 类

想添加spring security到你的应用中第一步是创建 Spring Security Java Configuration(配置).

这个配置创建一个叫 springSecurityFilterChain 的servlet 过滤器,来对我们应用中的所有的安全相关事项负责。

代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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;
 
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
 
     
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
        auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
    }
     
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       
      http.authorizeRequests()
        .antMatchers("/", "/home").permitAll()
        .antMatchers("/admin/**").access("hasRole('ADMIN')")
        .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
        .and().formLogin().loginPage("/login")
        .usernameParameter("ssoId").passwordParameter("password")
        .and().csrf()
        .and().exceptionHandling().accessDeniedPage("/Access_Denied");
    }
}

这个类和 上一篇文章 中几乎是一样的。唯一的区别是:

代码语言:javascript
复制
.and().formLogin().loginPage("/login")
        .usernameParameter("ssoId").passwordParameter("password")
        .and().csrf()

这段代码指定url为"/login"作为自定义的登录界面,并用 ssoId  作为用户名和password 作为密码参数。

我们也添加了一个可选方法 csrf()的调用,默认在Spring Security 4中该方法是激活的。

然而此调用是需要的,如果你先关闭csrf保护可以通过调用csrf().disable() 来实现,虽然这不是一个好主意。

上面的安全配置对应的XML 形式如下:

代码语言:javascript
复制
第4步: 注册springSecurityFilter

下面初始化类注册  springSecurityFilter  (在第3步中创建的)。

代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
 
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
 
}

此类和上一篇文章一模一样。

上面的配置对应的xml配置如下:

代码语言:javascript
复制
    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy

 

    springSecurityFilterChain
    /*
第5步: 添加Controller(控制器)
代码语言:javascript
复制
package com.websystique.springsecurity.controller;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
public class HelloWorldController {
 
     
    @RequestMapping(value = { "/", "/home" }, method = RequestMethod.GET)
    public String homePage(ModelMap model) {
        model.addAttribute("greeting", "Hi, Welcome to mysite");
        return "welcome";
    }
 
    @RequestMapping(value = "/admin", method = RequestMethod.GET)
    public String adminPage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "admin";
    }
     
    @RequestMapping(value = "/db", method = RequestMethod.GET)
    public String dbaPage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "dba";
    }
 
    @RequestMapping(value = "/Access_Denied", method = RequestMethod.GET)
    public String accessDeniedPage(ModelMap model) {
        model.addAttribute("user", getPrincipal());
        return "accessDenied";
    }
 
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginPage() {
        return "login";
    }
 
    @RequestMapping(value="/logout", method = RequestMethod.GET)
    public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){    
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "redirect:/login?logout";
    }
 
    private String getPrincipal(){
        String userName = null;
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
 
        if (principal instanceof UserDetails) {
            userName = ((UserDetails)principal).getUsername();
        } else {
            userName = principal.toString();
        }
        return userName;
    }
 
}

和上一篇文章的区别在于添加了  loginPage方法来处理“/login”请求,改变logout方法,退出后重定向到登录界面

代码语言:javascript
复制
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage() {
    return "login";
}
 
@RequestMapping(value="/logout", method = RequestMethod.GET)
public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null){    
        new SecurityContextLogoutHandler().logout(request, response, auth);
    }
    return "redirect:/login?logout";
}
第6步: 添加 SpringMVC Configuration(配置)类
代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.JstlView;
 
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springsecurity")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{
     
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
 
        return viewResolver;
    }
 
     /*
     * Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
}

和之前的不同是拓展自  WebMvcConfigurerAdapter类并覆盖了addResourceHandlers 方法来处理静态资源,使其可以在view中使用。

---------译者增加 start---明明如月-------- 以上配置对应的xml配置如下:

代码语言:javascript
复制
    /static/**" location="/static/" />

---------译者增加end---明明如月--------

第7: 添加Initializer(初始化器)类
代码语言:javascript
复制
package com.websystique.springsecurity.configuration;
 
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 
    @Override
    protected Class[] getRootConfigClasses() {
        return new Class[] { HelloWorldConfiguration.class };
    }
  
    @Override
    protected Class[] getServletConfigClasses() {
        return null;
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
 
}

此类和上一篇文章也是一样的。

第 8步: 添加Views(视图)

login.jsp

此视图为登录面板增加了css

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

    
        
        Login page
        
        
        
    
 
    
        
            
                
                    
                        
                        
                            
                                
                                    Invalid username and password.
                                
                            
                            
                                
                                    You have been logged out successfully.

注意:和 CSRF 相关的是

< input type = "hidden" name = "${_csrf.parameterName}" value = "${_csrf.token}" /> strong >

这一行的目的是防止CSRF攻击。正如你所见jsp中CSRF参数使用EL表达式获取的。因此需要允许el表达式:

需要在jsp头添加如下一行:

代码语言:javascript
复制
<%@ page isELIgnored="false"%>

welcome.jsp

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>


    
    Welcome page


    Greeting : ${greeting}
    This is a welcome page.

admin.jsp

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>


    
    Admin page


    Dear ${user}, Welcome to Admin Page.
    ">Logout

dba.jsp

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>


    
    DBA page


    Dear ${user}, Welcome to DBA Page.
    ">Logout

accessDenied.jsp

代码语言:javascript
复制
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>


    
    AccessDenied page


    Dear ${user}, You are not authorized to access this page
    ">Logout

例子中所需的css文件

app.css

代码语言:javascript
复制
html{
    background-color:#2F2F2F;
}
 
body, #mainWrapper {
    height: 100%;
    background-image: -webkit-gradient(
    linear,
    right bottom,
    right top,
    color-stop(0, #EDEDED),
    color-stop(0.08, #EAEAEA),
    color-stop(1, #2F2F2F),
    color-stop(1, #AAAAAA)
);
background-image: -o-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: -moz-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: -webkit-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: -ms-linear-gradient(top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
background-image: linear-gradient(to top, #EDEDED 0%, #EAEAEA 8%, #2F2F2F 100%, #AAAAAA 100%);
}
 
body, #mainWrapper, .form-control{
    font-size:12px!important;
}
 
#mainWrapper {
    height: 100vh; 
    padding-left:10px;
    padding-right:10px;
    padding-bottom:10px;
}
 
#authHeaderWrapper{
    clear:both;
    width: 100%;
    height:3%;
    padding-top:5px;
    padding-bottom:5px;
}
 
.login-container {
    margin-top: 100px;
    background-color: floralwhite;
    width: 40%;
    left: 30%;
    position: absolute;
}
 
.login-card {
    width: 80%;
    margin: auto;
}
.login-form {
    padding: 10%;
}
第9步: 构建和部署应用

现在构建 war 包(通过eclipse或者myeclipse)或者通过maven 命令行(  mvn clean install). 在一个 Servlet 3.0 容器中发布本应用. 在这里我使用的是tomcat, 我将 war 文件放到  tomcat webapps 文件夹然后点击 tomcat安装目录的bin文件夹下的 start.bat .

启动应用 打开浏览器 在地址栏输入 localhost:8080/SpringSecurityHelloWorldAnnotationExample/并回车

现在试着访问admin界面

localhost:8080/SpringSecurityCusotmLoginFormAnnotationExample/admin

将会触发登录界面

输入一个 USER 角色的账户

提交后 将显示 权限拒绝界面

点击 退出 并尝试访问admin页面

输入错误的密码

输入正确的admin账户

现在通过localhost:8080/SpringSecurityCusotmLoginFormAnnotationExample/db 访问db页面

将显示 权限拒绝界面

退出

下一篇文章实现自定义退出方法,并对浏览器后退按钮也进行了处理。

源码下载地址:http://websystique.com/?smd_process_download=1&download_id=1363

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016/05/05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第1步: 项目目录结构
  • 第2步:更新pom.xml文件添加需要的依赖
  • 第3步: 添加Spring Security Configuration 类
  • 第4步: 注册springSecurityFilter
  • 第5步: 添加Controller(控制器)
  • 第6步: 添加 SpringMVC Configuration(配置)类
  • 第7: 添加Initializer(初始化器)类
  • 第9步: 构建和部署应用
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档