`
zzc1684
  • 浏览: 1229242 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Spring Security笔记:使用数据库进行用户认证(form login using database)

阅读更多

在前一节,学习了如何自定义登录页,但是用户名、密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证

一、项目结构

与前面的示例相比,因为要连接db,所以多出了一个spring-database.xml用来定义数据库连接,此外,为了演示登录用户权限不足的场景,加了一个页面403.jsp,用来统一显示权限不足的提示信息

二、数据库表结构(oracle环境)

create table T_USERS
(
  d_username VARCHAR2(50) not null,
  d_password VARCHAR2(60),
  d_enabled  NUMBER(1)
);
alter table T_USERS
  add constraint PK_USERS_USERNAME primary key (D_USERNAME) ;
  
create table T_USER_ROLES
(
  d_user_role_id NUMBER(10) not null,
  d_username     VARCHAR2(50),
  d_role         VARCHAR2(50)
);
alter table T_USER_ROLES
  add constraint PK_USER_ROLES primary key (D_USER_ROLE_ID);
alter table T_USER_ROLES
  add constraint IDX_UNI_ROLE_USERNAME unique (D_USERNAME, D_ROLE);

create-table

 

这里创建了二张表,一张用来保存用户名/密码,另一张用来保存用户所属的权限角色,表名和字段名无所谓,可以随便改,但是用户表中,必须要有"用户名/密码/帐号的有效状态"这三列信息,权限角色表必须要有“用户名/权限角色”这二列信息

再insert几条测试数据

insert into T_USERS (D_USERNAME, D_PASSWORD, D_ENABLED)
values ('YJMYZZ', '123456', 1);

insert into T_USERS (D_USERNAME, D_PASSWORD, D_ENABLED)
values ('MIKE', 'MIKE123', 1); 

insert into T_USER_ROLES (D_USER_ROLE_ID, D_USERNAME, D_ROLE)
values (1, 'MIKE', 'POWER');

insert into T_USER_ROLES (D_USER_ROLE_ID, D_USERNAME, D_ROLE)
values (2, 'YJMYZZ', 'ADMIN');

insert into T_USER_ROLES (D_USER_ROLE_ID, D_USERNAME, D_ROLE)
values (3, 'YJMYZZ', 'POWER');

insert user/role data

 

这里插入了二个用户YJMYZZ/MIKE,而且MIKE属于POWER组,YJMYZZ同时属于POWER\ADMIN二个权限组

三、spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/admin**" access="hasRole('ADMIN')" />
        <!-- access denied page -->
        <access-denied-handler error-page="/403" />
        <form-login login-page="/login" default-target-url="/welcome"
            authentication-failure-url="/login?error" username-parameter="username"
            password-parameter="password" />
        <logout logout-success-url="/login?logout" />
        <!-- enable csrf protection -->
        <csrf />
    </http>

    <!-- Select users and user_roles from database -->
    <authentication-manager>
        <authentication-provider>
            <jdbc-user-service data-source-ref="dataSource"
                users-by-username-query="select d_username username,d_password password, d_enabled enabled from t_users where d_username=?"
                authorities-by-username-query="select d_username username, d_role role from t_user_roles where d_username=?  " />
        </authentication-provider>
    </authentication-manager>

</beans:beans>

spring-security

 

注意第9行,这里使用了一个el表达式,目的是/admin开头的url,必须有ADMIN角色的登录用户才可访问

第11行,表示如果登录用户权限不够,将跳转到/403这个url

24,25这二行,指定了查询用户/角色的sql语句,注意:虽然前面提到了用户/角色这二张表的表名/字段名可以随便写,但是写sql时,用户名的别名必须是username,密码列的别名必须是password,帐号有效状态的别名必须是enabled,而权限角色列的别名必须是role

23行指定了db数据源,它的详细定义在 spring-database.xml中,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@172.21.***.***:1521:orcl" />
        <property name="username" value="***" />
        <property name="password" value="***" />
    </bean>
</beans>

 

本文使用的是oracle数据库,如果是其它数据库,请自行调整上面的内容

四、Controller

package com.cnblogs.yjmyzz;

import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HelloController {

    @RequestMapping(value = { "/", "/welcome" }, method = RequestMethod.GET)
    public ModelAndView welcome() {

        ModelAndView model = new ModelAndView();
        model.addObject("title",
                "Spring Security Login Form - Database Authentication");
        model.addObject("message", "This is default page!");
        model.setViewName("hello");
        return model;

    }

    @RequestMapping(value = "/admin", method = RequestMethod.GET)
    public ModelAndView admin() {

        ModelAndView model = new ModelAndView();
        model.addObject("title",
                "Spring Security Login Form - Database Authentication");
        model.addObject("message", "This page is for ROLE_ADMIN only!");
        model.setViewName("admin");
        return model;

    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView login(
            @RequestParam(value = "error", required = false) String error,
            @RequestParam(value = "logout", required = false) String logout) {

        ModelAndView model = new ModelAndView();
        if (error != null) {
            model.addObject("error", "Invalid username and password!");
        }

        if (logout != null) {
            model.addObject("msg", "You've been logged out successfully.");
        }
        model.setViewName("login");

        return model;

    }

    // for 403 access denied page
    @RequestMapping(value = "/403", method = RequestMethod.GET)
    public ModelAndView accesssDenied() {

        ModelAndView model = new ModelAndView();

        // check if user is login
        Authentication auth = SecurityContextHolder.getContext()
                .getAuthentication();
        if (!(auth instanceof AnonymousAuthenticationToken)) {
            UserDetails userDetail = (UserDetails) auth.getPrincipal();
            model.addObject("username", userDetail.getUsername());
        }

        model.setViewName("comm/403");
        return model;

    }

}

HelloController

 

66-71行演示了如何在服务端判断一个用户是否已经登录

五、视图页面

hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="sec"
    uri="http://www.springframework.org/security/tags"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>${title}</title>
</head>
<body>
    <h1>Title : ${title}</h1>
    <h1>Message : ${message}</h1>
    <sec:authorize access="hasRole('POWER')">
        <!-- For login user -->
        <c:url value="/j_spring_security_logout" var="logoutUrl" />
        <form action="${logoutUrl}" method="post" id="logoutForm">
            <input type="hidden" name="${_csrf.parameterName}"
                value="${_csrf.token}" />
        </form>
        <script>
            function formSubmit() {
                document.getElementById("logoutForm").submit();
            }
        </script>

        <c:if test="${pageContext.request.userPrincipal.name != null}">
            <h2>
                User : ${pageContext.request.userPrincipal.name} | <a
                    href="javascript:formSubmit()"> Logout</a> | <a href="admin">admin</a>
            </h2>
        </c:if>
    </sec:authorize>

    <sec:authorize access="isAnonymous()">
        <br />
        <h2>
            <a href="login">login</a>
        </h2>
    </sec:authorize>

</body>
</html>

hello.jsp

 

注意一下:14、27、35这三行,它们演示了如何在jsp端判断用户具有的角色权限、是否已登录等用法

403.jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
    <h1>HTTP Status 403 - Access is denied</h1>

    <c:choose>
        <c:when test="${empty username}">
            <h2>You do not have permission to access this page!</h2>
        </c:when>
        <c:otherwise>
            <h2>
                Username : ${username} <br /> You do not have permission to access
                this page!
            </h2>
        </c:otherwise>
    </c:choose>

</body>
</html>

403.jsp

 admin.jsp

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>
<html>
<body>
    <h1>Title : ${title}</h1>
    <h1>Message : ${message}</h1>

    <c:url value="/j_spring_security_logout" var="logoutUrl" />
    <form action="${logoutUrl}" method="post" id="logoutForm">
        <input type="hidden" name="${_csrf.parameterName}"
            value="${_csrf.token}" />
    </form>
    <script>
        function formSubmit() {
            document.getElementById("logoutForm").submit();
        }
    </script>

    <c:if test="${pageContext.request.userPrincipal.name != null}">
        <h2>
            Welcome : ${pageContext.request.userPrincipal.name} | <a
                href="javascript:formSubmit()"> Logout</a> | <a href="welcome">welcome</a>
        </h2>
    </c:if>

</body>
</html>

admin.jsp

 

因为在xml中已经配置了/admin开头的请求url,必须具有ADMIN角色权限,所以admin.jsp端反而不用任何额外的判断了

文中示例源代码下载:SpringSecurity-LoginForm-Database-XML.zip

参考文章: Spring Security Form Login Using Database

分享到:
评论

相关推荐

    SpringSecurity笔记,编程不良人笔记

    - **UserDetailsService**: 这是一个接口,用于加载用户的详细信息,通常用于从数据库中获取用户数据进行认证。 2. **SpringSecurity配置** - XML配置:早期版本的SpringSecurity使用XML配置,但现在已被注解配置...

    Spring Security 把授权信息写入数据库

    目标是将现有的Acegi配置迁移到Spring Security 2.0,同时保持使用数据库作为认证和授权数据源的能力,避免依赖XML配置文件。 24.3. 实现步骤 要实现这一目标,首先需要将Spring Security 2.0的库文件添加到项目的...

    springsecurity学习笔记

    在"springsecurity学习笔记"中,你可能会涉及以下主题: - Spring Security的基本配置,包括web安全配置和全局安全配置。 - 如何自定义认证和授权流程,比如实现自定义的AuthenticationProvider和...

    spring-security使用数据库用户认证

    在本主题中,我们将深入探讨如何使用Spring Security与数据库配合,实现用户认证。这一过程涉及多个步骤,包括配置、数据库模型、用户DetailsService 和权限控制。 1. **配置Spring Security** 在Spring Security...

    spring security3笔记

    - **Form Login**:Spring Security提供内置的登录表单处理,包括登录页面和登录失败/成功处理器。 - **CSRF保护**:防止跨站请求伪造攻击,Spring Security通过生成和验证CSRF令牌来实现。 - **Session ...

    基本的spring mvc + spring security实现的登录(无数据库)

    - Spring Security的过滤器链接收到请求,由AuthenticationManager进行认证。 - 如果认证成功,SecurityContextHolder会存储Authentication对象,表示用户已认证。 - 接下来的请求会被Spring Security的权限检查...

    Spring Security 资料合集

    这三份资料——"实战Spring Security 3.x.pdf"、"Spring Security 3.pdf" 和 "Spring Security使用手册.pdf" 将深入探讨这些概念,并提供实践指导,帮助读者掌握如何在实际项目中应用Spring Security。通过学习这些...

    Spring Security笔记.rar

    本笔记将深入探讨Spring Security的核心概念、配置以及如何在实际项目中应用。 一、Spring Security核心概念 1. **身份验证(Authentication)**:这是验证用户身份的过程。Spring Security提供了多种方式来实现,...

    SpringSecurity 2 权限基于数据库--完整DEMO(带数据库文件)

    SpringSecurity是Java应用中广泛使用的安全框架,它提供了一种强大的方法来保护应用程序免受未经授权的访问和操作。本DEMO展示了如何将SpringSecurity与SSH(Spring、Struts2、Hibernate)集成,实现基于数据库的...

    Spring Security 安全实例-数据库简单应用(用户从数据库中获取)

    数据库用户存储配置 在传统的Spring Security配置中,用户信息通常被硬编码在配置文件中。然而,这种方式在实际项目中并不适用,因为用户数据通常需要存储在数据库中。以下是将用户信息从配置文件迁移到数据库的...

    SpringSecurity笔记2-SpringSecurity命名空间

    例如,`&lt;form-login login-processing-url="/j_spring_security_check" login-page="/login" /&gt;`表示提交登录信息到"/j_spring_security_check"路径,而登录页面是"/login"。 接着,`&lt;intercept-url&gt;`元素用于定义...

    spring security 使用数据库管理资源

    6. **Security Configuration**:在Spring Security配置中,需要声明使用数据库进行认证和授权的设置,例如使用`@EnableWebSecurity`和`WebSecurityConfigurerAdapter`的子类,覆盖其方法来配置相应的安全规则。...

    Spring Security数据库认证实例(dao认证)

    在数据库认证的场景中,Spring Security允许我们存储用户信息和权限在数据库中,而不是在内存或者静态配置文件中。这使得系统更加灵活,易于管理和扩展。 **1. Spring Security核心组件** - **Authentication**:...

    spring-security-login-form-database-xml.zip_java security

    标题 "spring-security-login-form-database-xml.zip_java security" 提示我们关注的是一个关于Spring Security的登录应用程序,其中涉及到数据库和XML配置。Spring Security是Java应用程序中广泛使用的安全框架,它...

    读书笔记:Spring Security OAuth2.0认证授权案例实战。.zip

    读书笔记:Spring Security OAuth2.0认证授权案例实战。

    Spring security认证授权

    在这个例子中,我们将深入探讨如何使用Spring Security进行认证和授权,并结合数据库操作进行动态配置。 首先,Spring Security的核心概念包括认证(Authentication)和授权(Authorization)。认证是确认用户身份...

    Spring Security 安全实例-数据库应用(用户从数据库中获取) 2

    在本实例中,我们将深入探讨如何使用Spring Security框架来实现基于数据库的安全管理,尤其是在用户认证和授权方面。Spring Security是一个强大的、高度可配置的安全框架,适用于Java和Java EE应用程序。它提供了一...

    Spring Security OAuth2.0学习笔记.zip

    Spring Security OAuth2.0学习笔记 什么是认证、授权、会话。 Java Servlet为支持http会话做了哪些事儿。 基于session认证机制的运作流程。 基于token认证机制的运作流程。 理解Spring Security的工作原理,Spring ...

    springboot springsecurity动态权限控制

    Spring Boot简化了Spring应用的初始搭建以及开发过程,而Spring Security则提供了全面的安全管理解决方案,包括认证、授权等。在这个“springboot springsecurity动态权限控制”的主题中,我们将深入探讨如何在...

Global site tag (gtag.js) - Google Analytics