1.权限控制
1.1认证和授权概念
以此项目为例:https://gitee.com/fan-shuaiqiang/health-project
该项目的功能有:检查项管理、检查组管理、套餐管理、预约管理等。
我们来思考以下两个问题:
- 问题1:在生产环境下,如果我们不登录后台系统可以操作这些功能吗?
- 答案当然是不能的,我们不能让任何人都能操作我们的系统,要进行相关操作必须先登录到系统上。
- 问题2:是不是所有用户,只要登录成功就可以操作所有的功能呢?
- 答案当然也是不能,不同的用户可能有不同的权限,这就需要对不同用户进行授权。
由此我们可以得出,要想实现权限控制,必须要进行认证和授权:
- 认证:系统提供的用于识别用户身份的功能,通常我们提供用户名和密码进行登录就是认证,认证的目的是让系统知道你是谁。
- 授权:用户认证成功后,需要为用户授权,其实就是指定当前用户可以操作哪些功能。对于一个系统,普通用户和管理员所看到的页面和能够进行的操作是不同的。
1.2权限模块数据模型
前面已经分析了认证和授权的概念,而要想实现最终的权限控制,需要有一套表结构支撑。
通常,我们用7张表来构成权限模块数据模型,分别为:
- 用户表(t_user):存放用户的基本信息,如:用户名、密码。
- 角色表(t_role):存放为系统分配的不同角色。如:普通用户、管理员。
- 用户角色关联表(t_user_role):用户登录到系统之后,我们要为其分配角色。同时,因为一个用户可能对应多个角色,一个角色也可能对应多个用户,是多对多的关系,所以需要在用户表和角色表之间创建一张关联表。
- 权限表(t_permission):存放对系统可执行的操作,如:增加检查项、删除检查项。
- 角色权限关联表(t_role_permission):我们要为不同角色授予不同的操作权限,角色和权限之间也是多对多的关系,故需要在角色表和权限表之间创建一张关联表。
- 菜单表(t_menu):存放不同的网页链接地址,如:会员管理页面、套餐设置页面、用户预约页面等。
- 角色菜单关联表(t_role_menu):为不同角色分配不同的页面,角色和页面之间也是多对多的关系,也需要一张关联表。
表之间关系如下图:
由上图可看出,在这7张表中,角色表起到了及其重要的作用,其位于核心位置,与用户表、权限表和菜单表都是多对多的关系。
我们可以分析一下在认证和授权过程中分别会使用到哪些表:
认证过程:只需要用户表即可,在用户登录时可以根据用户输入的用户名和密码来查询用户表,从而实现校验。
授权过程:用户必须完成认证后才能进行授权
- 首先可以根据用户查询其对应的角色。
- 再根据其角色查询对应的菜单,如此就确定了用户可以看到哪些菜单。
- 然后再根据其角色查询对应的权限,如此就确定了用户可执行的操作。
授权过程会用到上面的7张表。
2.Spring Security介绍
Spring Security是Spring提供的安全认证服务的框架。使用Spring Security可以帮助我们来简化认证和授权的过程。
官网:https://spring.io/projects/spring-security
对应的maven坐标:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
常用的权限控制框架除了Spring Security,还有Apache的shiro框架。
3.入门案例
3.1项目搭建
创建maven web工程spring-security-project,打包方式为war,然后在pom.xml中加入依赖。
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tsccg</groupId>
<artifactId>springsecuritydemo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<junit.version>4.12</junit.version>
<spring.version>5.0.5.RELEASE</spring.version>
<spring.security.version>5.0.5.RELEASE</spring.security.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>85</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.2配置web.xml
在web.xml中主要配置SpringMVC的DispatcherServlet和用于整合第三方框架的DelegatingFilterProxy,用于整合Spring Security。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
3.3配置Spring-security.xml(重点理解)
在spring-security.xml中主要配置Spring Security的拦截规则和认证管理器。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="admin" password="{noop}123456" authorities="ROLE_ADMIN"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
3.4创建index.html
在webapp目录下创建一个index.html,只有当登录成功时,才能看到该页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
欢迎登录系统页面!
</body>
</html>
3.5入门案例测试
启动服务,在浏览器地址栏输入:http://localhost:85/index.html
点击回车后,浏览器并没有跳转到index.html页面,而是跳转到了一个login页面。这是Spring Security默认的登录页面。
输入错误的用户名和密码:
输入正确的用户名和密码:
4.对入门案例改进
分析:
在前面的入门案例中,我们可以看出,Spring Security将我们项目中所有的资源都保护了起来,要想访问这些资源必须要完成认证而且需要具有ROLE_ADMIN角色。
但是入门案例中使用的方法距离我们真实的生产环境还差的远,还存在如下一些问题:
- 不可匿名访问:项目中我们将所有的资源都保护了起来(拦截所有请求URL),但在实际环境下往往有一些资源不需要认证也能访问,也就是匿名访问。比如说我们自己写的登录页面。
- 没有使用指定的登录页面:登录页面是由框架生成的,而我们的项目往往会使用自己的登录页面。
- 没有动态地获取用户名密码:直接将用户名和密码配置在了配置文件中,而真实环境下的用户名和密码往往保存在数据库里。
- 密码为非加密的明文:在配置文件中配置的密码使用的是明文,非常不安全,在真实环境下需要对密码进行加密。
4.1配置可匿名访问的资源
第一步:在项目中创建pages目录,在pages目录中创建a.html和b.html
第二步:在spring-security.xml文件中配置,指定哪些资源可以匿名访问
<security:http security="none" pattern="/pages/a.html"/>
<security:http security="none" pattern="/pages/b.html"/>
<security:http security="none" pattern="/pages/**"/>
第三步:测试
开启服务,在浏览器中访问pages目录下的a.html和b.html。以及被保护的index.html
4.2使用指定的登录页面
第一步:提供login.html作为项目的登录页面
在webapp目录下新建login.html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
<link rel="shortcut icon" href="#"/>
</head>
<body>
<center>
<h2>自定义登录页面</h2>
<form action="/login.do" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</center>
</body>
</html>
第二步:修改spring-security.xml文件,指定login.html页面可以被匿名访问
<security:http security="none" pattern="/login.html"/>
第三步:修改spring-security.xml文件,配置自定义表单登录信息。位置:security:http中。
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.html"
authentication-failure-url="/login.html"
/>
form-login自定义表单登录信息:
- login-page:登录页面路径
- username-parameter:告诉Spring Security框架用户名输入框的name属性值
- password-parameter:告诉Spring Security框架密码输入框的name属性值
- login-processing-url:告诉框架要处理的登录请求url
- default-target-url:登录成功后,默认跳转的页面路径
- authentication-failure-url:登录失败后,跳转的页面路径
我们不需要自己写Controller来处理登录请求,Spring Security会处理。
第四步:修改spring-security.xml文件,关闭CsrfFilter过滤器。位置:security:http中。
<security:csrf disabled="true"/>
完整配置:
<security:http security="none" pattern="/login.html"/>
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.html"
authentication-failure-url="/login.html"
/>
<security:csrf disabled="true"/>
</security:http>
第五步:测试
开启服务,通过浏览器访问index.html
输入错误用户名密码
输入正确用户名密码
4.3从数据库查询用户信息
4.3.1编写UserDetailsService接口的实现类
如果我们要从数据库动态查询用户信息,就必须按照spring security框架的要求提供一个实现UserDetailsService接口的实现类,并按照框架的要求进行配置即可。框架会自动调用实现类中的方法并自动进行密码校验。
实现类代码:
package com.tsccg.service;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserService implements UserDetailsService {
private static Map<String, MyUser> userInDB = new HashMap<>();
static {
MyUser user1 = new MyUser("admin","123456");
userInDB.put(user1.getUsername(),user1);
MyUser user2 = new MyUser("lisi","123456");
userInDB.put(user2.getUsername(),user2);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println(username);
MyUser myUser = userInDB.get(username);
if (myUser == null) {
return null;
}
String passwordInDB = "{noop}" + myUser.getPassword();
List<GrantedAuthority> list = new ArrayList<>();
list.add(new SimpleGrantedAuthority("PERMISSION_ADD"));
list.add(new SimpleGrantedAuthority("PERMISSION_DELETE"));
if ("admin".equals(username)) {
list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
User securityUser = new User(username,passwordInDB,list);
return securityUser;
}
}
class MyUser {
private String username;
private String password;
public MyUser() {
}
public MyUser(String username, String password) {
this.username = username;
this.password = password;
}
}
4.3.2引用实现类
在spring配置文件中注册UserService,指定其作为认证过程中根据用户名查询用户信息的处理类。
spring-security.xml:
<bean id="userService" class="com.tsccg.service.UserService"/>
<security:authentication-manager>
<security:authentication-provider user-service-ref="userService">
</security:authentication-provider>
</security:authentication-manager>
4.3.3测试
前面我们提供了UserService实现类,并且按照框架的要求实现了UserDetailsService接口。
在spring配置文件中注册UserService,指定其作为认证过程中根据用户名查询用户信息的处理类。
当我们进行登录操作时,spring security框架会调用UserService的loadUserByUsername方法查询用户信息,并根据此方法中提供的密码和用户页面输入的密码进行比对来实现认证操作。
当用户名为"lisi"时,由于未授予其"ROLE_ADMIN"角色,故没有权限登录。
4.4对密码进行加密
前面我们使用的密码都是明文的,这是非常不安全的。一般情况下用户的密码需要进行加密后再保存到数据库中。
常见的密码加密方式有:
3DES、AES、DES:使用对称加密算法,可以通过解密来还原出原始密码
MD5、SHA1:使用单向HASH算法,无法通过计算还原出原始密码,但是可以建立彩虹表进行查表破解
bcrypt:将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题
加密后的格式一般为:
$2a$10$/bTVvqqlH9UiE0ZJZ7N2Me3RIgUCdgMheyTgV0B4cMCSokPa.6oCa
加密后字符串的长度为固定的60位。其中:$是分割符,无意义;2a是bcrypt加密版本号;10是cost的值;而后的前22位是salt值;再然后的字符串就是密码的密文了。
实现步骤:
第一步:在spring-security.xml文件中指定密码加密对象
<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<bean id="userService" class="com.tsccg.service.UserService"/>
<security:authentication-manager>
<security:authentication-provider user-service-ref="userService">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<context:annotation-config/>
第二步:修改UserService实现类
package com.tsccg.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserService implements UserDetailsService {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
private Map<String, MyUser> userInDB = new HashMap<>();
public void initUserData() {
MyUser user1 = new MyUser("admin",passwordEncoder.encode("123456"));
userInDB.put(user1.getUsername(),user1);
MyUser user2 = new MyUser("lisi",passwordEncoder.encode("123456"));
userInDB.put(user2.getUsername(),user2);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
initUserData();
MyUser myUser = userInDB.get(username);
if (myUser == null) {
return null;
}
String passwordInDB = myUser.getPassword();
List<GrantedAuthority> list = new ArrayList<>();
list.add(new SimpleGrantedAuthority("PERMISSION_ADD"));
list.add(new SimpleGrantedAuthority("PERMISSION_DELETE"));
if ("admin".equals(username)) {
list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
User securityUser = new User(username,passwordInDB,list);
return securityUser;
}
}
class MyUser {
private String username;
private String password;
public MyUser() {
}
public MyUser(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
第三步:进行测试
4.5定义多种校验规则
为了测试方便,首先在项目中/webapp/pages 目录下创建a.html、b.html、c.html、d.html几个页面
步骤一:修改spring-security.xml文件:
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/pages/a.html" access="isAuthenticated()"/>
<security:intercept-url pattern="/pages/b.html" access="hasAuthority('add')"/>
<security:intercept-url pattern="/pages/c.html" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/pages/d.html" access="hasRole('ADMIN')"/>
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.html"
authentication-failure-url="/login.html"
/>
<security:csrf disabled="true"/>
</security:http>
步骤二:修改修改UserService实现类
当用户名为admin时,为其添加add 权限
步骤3:测试
当用户名为lisi时:
lisi只能访问a.html。
当用户名为admin时:
admin可访问所有页面。
4.6注解方式权限控制(方法级别-常用)
Spring Security除了可以在配置文件中配置权限校验规则,还可以使用注解方式控制类中方法的调用。
例如Controller中的某个方法要求必须具有某个权限才可以访问,此时就可以使用Spring Security框架提供的注解方式进行控制。
实现步骤:
第一步:在spring-security.xml文件中添加校验规则,只要认证通过即可访问以/user/*结尾的请求
<security:intercept-url pattern="/user/*" access="isAuthenticated()"/>
第二步:在spring-security.xml文件中配置组件扫描,用于扫描Controller
<mvc:annotation-driven/>
<context:component-scan base-package="com.tsccg.controller"/>
第三步:在spring-security.xml文件中开启权限注解支持
<security:global-method-security pre-post-annotations="enabled"/>
第四步:创建Controller类并在处理器方法上加入注解进行权限控制
package com.tsccg.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/find")
public String find() {
System.out.println("find...");
return "find success...";
}
@RequestMapping("/add")
@PreAuthorize("hasAuthority('add')")
public String add() {
System.out.println("add...");
return "add success...";
}
@RequestMapping("/delete")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String delete() {
System.out.println("delete...");
return "delete success...";
}
}
第五步:测试
①用户名为:lisi
lisi没有add权限和ROLE_ADMIN角色,只能访问find方法。
②用户名为admin
admin有add权限以及ROLE_ADMIN角色,所有方法都可以访问
4.7退出登录
用户完成登录后,Spring Security框架会记录当前用户认证状态为已认证状态,即表示用户登录成功了。但用户如何退出登录呢?我们可以在spring-security.xml文件中进行如下配置:
<security:http 中
<security:logout logout-url="/logout.do"
logout-success-url="/login.html"
invalidate-session="true"
/>
测试:
4.8spring-security.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http security="none" pattern="/login.html"/>
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/pages/a.html" access="isAuthenticated()"/>
<security:intercept-url pattern="/pages/b.html" access="hasAuthority('add')"/>
<security:intercept-url pattern="/pages/c.html" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/pages/d.html" access="hasRole('ADMIN')"/>
<security:intercept-url pattern="/user/*" access="isAuthenticated()"/>
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.html"
authentication-failure-url="/login.html"
/>
<security:csrf disabled="true"/>
<security:logout logout-url="/logout.do"
logout-success-url="/login.html"
invalidate-session="true"
/>
<security:headers>
<security:frame-options policy="SAMEORIGIN"/>
</security:headers>
</security:http>
<bean id="userService" class="com.tsccg.service.UserService"/>
<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<security:authentication-manager>
<security:authentication-provider user-service-ref="userService">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<context:annotation-config/>
<mvc:annotation-driven/>
<context:component-scan base-package="com.tsccg.controller"/>
<security:global-method-security pre-post-annotations="enabled"/>
</beans>
|