SpringBoot28-springboot企业级开发-安全控制Spring Security

一,Spring Security快速入门

1,什么是Spring Security   

     Spring Security是专门针对基于Spring的项目的安全框架,充分利用了依赖注入和AOP来实现安全的功能。

     在早期的Spring Security版本,使用Spring Security需要使用大量的xml配置,而下面将全部基于Java配置来实现Spring Security的功能。

     安全框架有两个重要的概念,即认证(Authentication)和授权(Authorization)。认证即确认用户可以访问当前系统;授权即确定用户在当前系统下所拥有的功能权限,下面将围绕认证和授权展开。


2,Spring Security的配置

1)DelegatingFilterProxy  

    Spring Security为我们提供了一个多个过滤器来实现所有安全的功能,我们只需注册一个特殊的DelegatingFilterProxy过滤器到WebAppliactionInitializer即可。

        而在实际使用中,我们只需让自己的Initializer类继承AbstractSecurityWebApplicationInitializer抽象类即可。AbstractSecurityWebApplicationInitializer实现了WebApplicationInitializer接口,并通过onStartup方法调用:

       insertSpringSecurityFilterChain(servletContext);

       它为我们注册了DelegatingFilterProxy。insertSpringSecurityFilterChain源码如下:

private void insertSpringSecurityFilterChain(ServletContext servletContext) {
        String filterName = "springSecurityFilterChain";
        DelegatingFilterProxy springSecurityFilterChain = new DelegatingFilterProxy(filterName);
        String contextAttribute = this.getWebApplicationContextAttribute();
        if (contextAttribute != null) {
            springSecurityFilterChain.setContextAttribute(contextAttribute);
        }

        this.registerFilter(servletContext, true, filterName, springSecurityFilterChain);
    }

   所以我们只需要用以下代码即可开启Spring Security的过滤器支持:

package com.jack.springboot12springsecurit.controller;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

/**
 * create by jack 2017/10/12
 */
public class AppInitializer extends AbstractSecurityWebApplicationInitializer{
}

2)配置

      Spring Security的配置和Spring MVC的配置类似,只需在一个配置类上注解@EnableWebSecurity,并让这个类继承WebSecurityConfigurerAdapter即可。我们可以通过重写configure方法来配置相关的安全配置。代码如下:

package com.jack.springboot12springsecurit.config;

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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * create by jack 2017/10/12
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }
}


3,用户认证

      认证需要我们有一套用户数据的来源,而授权则是对于某个用户有相应的角色权限。在Spring Security里我们通过重写

 @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

   方法来实现。


1)内存中的用户

      使用AuthenticationManagerBuilder的inMemoryAuthentication方法即可添加在内存中的用户,并可给用户指定角色权限。

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //super.configure(auth);
        auth.inMemoryAuthentication()
                .withUser("jack1").password("jack1").roles("ROLE_ADMIN")
                .and()
                 .withUser("jack2").password("jack2").roles("ROLE_USER");
    }

2)JDBC中的用户

      JDBC中的用户之间指定dataSource即可。

package com.jack.springboot12springsecurit.config;

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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import javax.sql.DataSource;

/**
 * create by jack 2017/10/12
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired
    private DataSource dataSource;
   
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //super.configure(auth);
        auth.jdbcAuthentication().dataSource(dataSource);
    }
}

         不过这看上去很奇怪,其实这里的Spring Security是默认了你的数据库结构的。通过jdbcAuthentication的源码,我们可以看出在JdbcDaoImpl中定义了默认的用户及角色权限获取的sql语句:

     

public static final String DEF_USERS_BY_USERNAME_QUERY = "select username,password,enabled from users where username = ?";
public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "select username,authority from authorities where username = ?";

public static final String DEF_USERS_BY_USERNAME_QUERY = "select username,password,enabled from users where username = ?";
    public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "select username,authority from authorities where username = ?";


       当然我们可以自定义我们的查询用户和权限的sql语句,例如:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //super.configure(auth);
        auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery("select username,password,true "
        + "from myusers where username = ?")
        .authoritiesByUsernameQuery("select username,role "
        +" from roles where username = ?");
    }

3)通用的用户

      上面的两种用户和权限的获取方式只限于内存或者jdbc,我们的数据访问方式可以是各种各样的,可以是非关系型数据库,也可以是我们常用的JPA等。

     这时我们需要自定义实现UserDetailsService接口。上面的内存中用户及JDBC用户就是UserDetailsService的实现,定义如下:

package com.jack.springboot12springsecurit.controller;

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 java.util.ArrayList;
import java.util.List;

/**
 * create by jack 2017/10/12
 */
public class CustomUserService implements UserDetailsService{
    @Autowired
    SysUserRepository userRepository;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user= userRepository.findByUserName(username);
        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        return new User(user.getUsername(),user.getPassword(),authorities);
    }
}

     说明:SysUser是我们系统的用户领域对象类,User来自于org.springframework.security.core.userdetails.User.

     除此之外,我们还需要注册这个CustomUserService,代码如下:

@Bean
    UserDetailsService customUserService(){
        return new CustomUserService();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserService());
    }


4,请求授权

       Spring Security是通过重写

@Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }

       方法来实现请求拦截的。

       Spring Security使用以下匹配器来匹配请求路径:

        antMatchers:使用Ant风格的路径匹配。

        regexMatchers:使用正则表达式匹配路径

 anyRequest:匹配所有请求路径。

 在匹配了请求路径后,需要针对当前用户的信息对请求路径进行安全处理,Spring Security提供了下面的安全处理方法:

access(String) :Spring EL表达式结构为true时可访问

anonymous():匿名可访问

denyAll():用户不能访问

fullyAuthenticated():用户完全认证可访问(非remember me下自动登入)

hasAnyAuthority(String...):如果用户有参数,则其中任一权限可访问

hasAnyRole(String...):如果用户有参数,则其中任一角色可访问

hasAuthority(String):如果用户有参数,则其权限可访问

hasIpAddress(String):如果用户来自参数中的ip则可访问

hasRole(String):若用户有参数中的角色可访问

permitAll():用户可任意访问

rememberMe():允许通过remember-me登录的用户访问

authenticated():用户登录后可访问


      我们可以看一下下面的示例代码:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()//通过authorizeRequests方法来开始请求权限配置
        .antMatchers("/admin/**").hasRole("ROLE_ADMIN")//请求匹配/admin/**,只有ROLE_ADMIN角色的用户可访问
        .antMatchers("/user/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")//请求匹配/user/**,拥有ROLE_ADMIN或ROLE_USER角色的用户都可访问
                .anyRequest().authenticated();//其余所有的请求都需要认证后(登入后)才可访问
    }


5,定制登入行为

      我们也可以通过重写

protected void configure(HttpSecurity http)
      方法来定制我们的登入行为。

      下面将重用的登入行为的定制以简短的代码演示:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        /*http
                .authorizeRequests()//通过authorizeRequests方法来开始请求权限配置
        .antMatchers("/admin/**").hasRole("ROLE_ADMIN")//请求匹配/admin/**,只有ROLE_ADMIN角色的用户可访问
        .antMatchers("/user/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")//请求匹配/user/**,拥有ROLE_ADMIN或ROLE_USER角色的用户都可访问
                .anyRequest().authenticated();//其余所有的请求都需要认证后(登入后)才可访问*/
        http
                .formLogin()//通过formLogin方法定制登录操作
        .loginPage("/login")//使用loginPage方法定制登入页面的访问地址
        .defaultSuccessUrl("/index")//defaultSuccessUrl指定登入成功后转向的页面
        .failureUrl("/login?error")//failureUrl指定登入失败后转向的页面
        .permitAll()
                .and()
                .rememberMe()//rememberMe开启cookie存储用户信息
        .tokenValiditySeconds(1209600)//tokenValiditySeconds指定cookie有效期为1209600秒,即两个星期
        .key("myKey")//指定cookie中的私钥
        .and()
                .logout()//使用logout方法定制注销行为
        .logoutUrl("/custom-logout")//logoutUrl指定注销的URL路径
        .logoutSuccessUrl("/logout-success")//logoutSuccessUrl指定注销成功后转向的页面
        .permitAll();
    }

二,Spring Boot的支持

       Spring Boot针对Spring Security的自动配置在org.springframework.boot.autoconfigure.security包中。

       主要通过SecurityAutoConfiguration和SecurityProperties来完成配置。

       SecurityAutoConfiguration导入SpringBootWebSecurityConfiguration中配置。在SpringBootWebSecurityConfiguration配置中,我们获得如下的自动配置:

1)自动配置了一个内存中的用户,账号为user,密码在程序启动时出现

2)忽略/css/**,/js/**,/images/**和/**/favicon.ico等静态文件的拦截。

3)自动配置的securityFilterChainRegistration的Bean.


    SecurityProperties使用“security”为前缀的属性配置Spring Security相关的配置,包含:

#内存中的用户默认账号为uer
security.user.name=user
#1默认用户的密码
security.user.password=
#默认用户的角色
security.user.role=USER
#是否需要ssl支持
security.require-ssl=false
#是否开启“跨战请求伪造”支持,默认关闭
security.enable-csrf=false
security.basic.enabled=true
security.basic.realm=Spring
# /**
security.basic.path=
security.basic.authorize-mode=
security.filter-order=0
security.headers.xss=true
security.headers.cache=true
security.headers.frame=true
security.headers.content-type=false
security.headers.hsts=all
security.sessions=stateless
#用逗号隔开的无须拦截的路径
security.ignored=


      Spring Boot为我们做了如此多的配置,当我们需要自己扩展的配置时,只需配置类继承WebSecurityConfigurerAdapter类即可,无须使用@EnableWebSecurity注解,例如:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{}


三,实战

      下面的示例中,演示使用Spring Boot下的Spring Security的配置,完成简单的认证授权的功能。下面我们将通过Spring Data JPA获得用户数据。页面模板使用Thymeleaf,Thymeleaf也为我们提供了支持Spring Security的标签。

1,新建Spring Boot项目

      新建Spring Boot项目,依赖JPA,Security,Thymeleaf,mysql驱动

     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.jack</groupId>
	<artifactId>springboot12springsecurit</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>springboot12springsecurit</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.7.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>

		<dependency>
			<groupId>org.thymeleaf.extras</groupId>
			<artifactId>thymeleaf-extras-springsecurity4</artifactId>
		</dependency>

		<!--mysql连接驱动-->
		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.39</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>


application.properties如下:

server.port=9090
spring.datasource.data-username=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/jack
spring.datasource.username=root
spring.datasource.password=root

logging.level.org.springframework.security=INFO

spring.thymeleaf.cache=false

spring.jpa.hibernate.ddl-auto=update

spring.jpa.show-sql=true


     将bootstrap.min.css放置在src/main/resources/static/css下,此路径默认不拦截

2,用户和角色

我们使用JPA来定义用户和角色

用户:

package com.jack.springboot12springsecurit.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * create by jack 2017/10/18
 */

/**
 * 让我们的用户实体实现UserDetailsService接口,我们的用户实体即为Spring Security所使用的用户
 */
@Entity
public class SysUser implements UserDetails{
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue//(strategy= GenerationType.AUTO)
    private Integer id;
    private String username;
    private String password;
    /**
     * 配置用户和角色的多对多关心
     */
    @ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER)
    private List<SysRole> roles;


    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * 重写getAuthorities方法,将用户的角色作为权限
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> auths = new ArrayList<>();
        List<SysRole> roles = this.roles;
        for (SysRole role:
             roles) {
            auths.add(new SimpleGrantedAuthority(role.getName()));
        }
        return auths;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<SysRole> getRoles() {
        return roles;
    }

    public void setRoles(List<SysRole> roles) {
        this.roles = roles;
    }
}


角色:

package com.jack.springboot12springsecurit.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 * create by jack 2017/10/18
 */
@Entity
public class SysRole {
    @Id
    @GeneratedValue//(strategy= GenerationType.AUTO)
    private Integer id;
    //角色名称
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

1)数据结构及初始化

   当我们配置用户和角色的多对多关心后,通过设置:

   spring.jpa.hibernate.ddl-auto=update

   为我们自动生成用户表:sys_user,角色表:sys_role,关联表:sys_user_roles.

   针对上面的结构,我们初始化一些数据来方便我们演示。在src/main/resources下,新建data.sql,即新建两个用户,角色分别为role_admin和role_user,代码如下:

INSERT INTO sys_user(id,username,password) VALUES (1,'jack1','jack1');
INSERT INTO sys_user(id,username,password) VALUES (2,'jack2','jack2');

INSERT INTO sys_role(id,name) VALUES (1,'ROLE_ADMIN');
INSERT INTO sys_role(id,name) VALUES (2,'ROLE_USER');

INSERT INTO sys_user_roles(sys_user_id,roles_id) VALUES (1,1);
INSERT INTO sys_user_roles(sys_user_id,roles_id) VALUES (2,2);

2)传值对象

     用来测试不同角色用户的数据展示:、

package com.jack.springboot12springsecurit.pojo;

/**
 * create by jack 2017/10/18
 */
public class Msg {
    private String title;
    private String content;
    private String etraInfo;

    public Msg(String title, String content, String etraInfo) {
        super();
        this.title = title;
        this.content = content;
        this.etraInfo = etraInfo;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getEtraInfo() {
        return etraInfo;
    }

    public void setEtraInfo(String etraInfo) {
        this.etraInfo = etraInfo;
    }
}

3,数据访问

    我们这里的数据访问很简单,代码如下:

package com.jack.springboot12springsecurit.dao;

import com.jack.springboot12springsecurit.entity.SysUser;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * create by jack 2017/10/18
 */
public interface SysUserRepository extends JpaRepository<SysUser,Integer> {
    SysUser findByUsername(String username);
}

  上面一个方法是根据用户名查询出用户


4,自定义UserDetailsService

package com.jack.springboot12springsecurit.service;

import com.jack.springboot12springsecurit.dao.SysUserRepository;
import com.jack.springboot12springsecurit.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

/**
 * create by jack 2017/10/18
 */

/**
 * 自定义需实现UserDetailsService接口
 */
public class CustomUserService implements UserDetailsService{
    @Autowired
    private SysUserRepository userRepository;

    /**
     * 重写loadUserByUsername方法获得用户
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        //我们当前的用户实现了UserDetails接口,可直接返回给Spring Security使用
        return user;
    }
}


5,配置

1)Spring MVC配置

package com.jack.springboot12springsecurit.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * create by jack 2017/10/18
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //super.addViewControllers(registry);
        registry.addViewController("/login").setViewName("login");
    }
}


   注册访问/login转向login.html页面


2)Spring Security配置

package com.jack.springboot12springsecurit.config;

import com.jack.springboot12springsecurit.service.CustomUserService;
import org.springframework.context.annotation.Bean;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * create by jack 2017/10/18
 */

/**
 * 扩展Spring Security配置需要继承WebSecurityConfigurerAdapter
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    /**
     * 注册CustomUserService的Bean
     * @return
     */
    @Bean
    UserDetailsService customUserService(){
        return new CustomUserService();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //super.configure(auth);
        /**
         * 添加我们自定义的user detail service认证
         */
        auth.userDetailsService(customUserService());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //super.configure(http);
        http.authorizeRequests()
                .anyRequest()
                .authenticated()//所有请求需要认证即登入后才能访问
                .and()
                .formLogin()
                .loginPage("/login")
                .successForwardUrl("/security/index")//登入成功后的跳转路径
                .failureUrl("/login?error")
                .permitAll()//定制登入行为,登入页面可任意访问
                .and()
                .logout()
                .permitAll();//定制注销行为,注销请求可任意访问
    }
}

6,页面

1)登录页面login.html,代码如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta content="text/html;charset=UTF-8"/>
    <title>security登入页面</title>
    <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/>
    <style type="text/css">
        body {
            padding-top: 50px;
        }

        .starter-template {
            padding: 40px 15px;
            text-align: center;
        }

    </style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">spring security演示</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
                <li><a th:href="@{/}">首页</a></li>
            </ul>
        </div><!--/.nav-collapse-->
    </div>
</nav>

<div class="container">
    <div class="starter-template">
        <!--注销成功后显示-->
        <p th:if="${param.logout}" class="bg-warning">已成功注销</p>
        <!--登入有错误时显示-->
        <p th:if="${param.error}" class="bg-danger">有错误,请重试</p>
        <h2>使用账户密码登入</h2>
        <!--默认的登入路径为/login(自Spring Security4.x开始)-->
        <form name="form" th:action="@{/login}" action="/login" method="post">
            <div class="form-group">
                <label for="username">账户</label>
                <input type="text" class="form-control" name="username" value="" placeholder="账户"/>
            </div>
            <div class="form-group">
                <label for="password">密码</label>
                <input type="password" class="form-control" name="password" placeholder="密码"/>
            </div>
            <input type="submit" id="login" value="Login" class="btn btn-primary"/>
        </form>
    </div>
</div>

</body>
</html>

2)主页,home.html代码如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<!--xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
是thymeleaf为我们提供的spring security的标签支持-->
<head>
    <meta content="text/html;charset=UTF-8"/>
    <!--通过sec:authentication="name"获得当前用户的用户名-->
    <title sec:authentication="name"></title>
    <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/>
    <style type="text/css">
        body {
            padding-top: 50px;
        }

        .starter-template {
            padding: 40px 15px;
            text-align: center;
        }

    </style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">spring security演示</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
                <li><a th:href="@{/}">首页</a></li>
            </ul>
        </div><!--/.nav-collapse-->
    </div>
</nav>

<div class="container">
    <div class="starter-template">
        <h1 th:text="${msg.title}"></h1>
        <p class="bg-primary" th:text="${msg.content}"></p>
        <!--sec:authentication="hasRole('ROLE_ADMIN')"意味着只有当前用户觉得为ROLE_ADMIN时
        ,才可显示标签内容-->
        <div sec:authorize="hasRole('ROLE_ADMIN')">
            <p class="bg-info" th:text="${msg.etraInfo}"></p>
        </div>
        <!--sec:authentication="hasRole('ROLE_USER')"意味着只有当前用户觉得为ROLE_USER时,才可
        显示标签内容-->
        <div sec:authorize="hasRole('ROLE_USER')">
            <p class="bg-info">无更多信息显示</p>
        </div>
        <form th:action="@{/logout}" method="post">
            <!--注销的默认路径为/logout,需通过post请求提交-->
            <input type="submit" class="btn btn-primary" value="注销"/>
        </form>
    </div>
</div>

</body>
</html>

7,控制器

     此控制器很简单,只为首页显示准备数据:

package com.jack.springboot12springsecurit.controller;

import com.jack.springboot12springsecurit.pojo.Msg;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * create by jack 2017/10/18
 */
@Controller
@RequestMapping("security")
public class SecurityController {
    @RequestMapping("/index")
    //@RequestMapping("/")
    public String index(Model model){
        Msg msg = new Msg("测试标题", "测试内容", "额外信息,只对管理员显示");
        model.addAttribute("msg", msg);
        return "home";
    }
}

8,运行

1)登入。访问http://localhost:9090/login,将会自动转到登录页面http://localhost:9090/login,如下:




使用正确的账号密码登录:

1,使用role_admin的用户进行登录:



使用错误的账号登录:




2)注销。登入成功后,点击注销按钮如下:



3)用户信息

     页面上我们将用户名显示在页面的标题上,如下:




    用jack1和jack2用户名登入,对应的角色不同,上面显示的视图也不一样。

    源代码地址:https://github.com/wj903829182/SpringCloudTwo/tree/master/springboot12springsecurit





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值