分享

Spring Boot使用Spring Security实现权限控制

 邵飞翔 2017-03-31

Spring Boot使用Spring Security实现权限控制

编辑时间:2016-12-29 浏览量:803

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI和AOP功能,为应用系统提供声明式的安全访问控制功能。那么Spring Boot怎样配置使用Spring Security呢?

下面以简单的例子来说明:

数据访问使用JPA,视图模板使用Thymeleaf

首先创建Spring Boot工程,导入JPA、Security、Thymeleaf的依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<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.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>

然后在src/main/resources下创建application.properties文件,配置如下:

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc\:mysql\://localhost\:3306/springboot?useUnicode\=true&characterEncoding\=utf-8&allowMultiQueries\=true
spring.datasource.username=root
spring.datasource.password=
logging.level.org.springframework.security=INFO
spring.thymeleaf.cache=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

在src/main/resources下创建static(存放静态资源)目录和template(存放视图模板)目录,将bootstrap的资源文件拷贝到static下,项目结构如下:

微儿博客

JPA会自动生成用户表(SYS_USER)、角色表(SYS_ROLE)、用户角色关联表(SYS_USER_ROLES)。

首先初始化一些数据,在src/main/resources下新建data.sql,插入一下代码:

insert into SYS_USER(id,username,password) values(1,'we','we');
insert into SYS_USER(id,username,password) values(2,'weare','weare');

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);

创建Msg类,用户数据的展示:

package com.springboot.security.entity;

public class Msg {

private String title;

private String content;

private String etraInfo;

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

/**
* @return the title
*/
public String getTitle() {
return title;
}

/**
* @param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}

/**
* @return the content
*/
public String getContent() {
return content;
}

/**
* @param content the content to set
*/
public void setContent(String content) {
this.content = content;
}

/**
* @return the etraInfo
*/
public String getEtraInfo() {
return etraInfo;
}

/**
* @param etraInfo the etraInfo to set
*/
public void setEtraInfo(String etraInfo) {
this.etraInfo = etraInfo;
}
}

创建数据访问层:

package com.springboot.security.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.springboot.security.entity.SysUser;

public interface SysUserReposity extends JpaRepository<SysUser, Long>{

SysUser findByUsername(String username);

}

创建Service层,自定义UserDetailsService

package com.springboot.security.service;

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;

import com.springboot.security.dao.SysUserReposity;
import com.springboot.security.entity.SysUser;
//实现UserDetailsService
public class UserDetailService implements UserDetailsService{

@Autowired
SysUserReposity sysUserReposity;
//重写loadUserByUsername方法
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser user = sysUserReposity.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("用户名不存在");
}
return user;//返回自定义的user对象
}
}

创建SpringMVC配置:

package com.springboot.security.config;

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

@Configuration
public class WebMVCConfig extends WebMvcConfigurerAdapter{

@Override
public void addViewControllers(ViewControllerRegistry registry) {
       //设置/login路径跳转login.html
registry.addViewController("/login").setViewName("login");
}
}

创建Spring Security配置:

package com.springboot.security.config;

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;

import com.springboot.security.service.UserDetailService;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Bean//注册我们自定义的UserDetailService Bean
public UserDetailsService userDetailsService() {
return new UserDetailService();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
               //添加自定义的userdetailservice认证        
auth.userDetailsService(userDetailsService());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()//所有请求需要认证登陆后才能访问
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.permitAll()//登录页面可任意访问
.and()
.logout()
.permitAll();//注销请求可任意访问
}
}

创建页面:

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.">
<head>
<meta charset="UTF-8"/>
<title>登陆页面</title>
<link th:href="@{css/bootstrap.min.css}" rel="stylesheet"/>
<style type="text/css">
body{
padding-top:50px;
}
.starter-template{
padding:40px 15px;
text-align:center;
}
</style>
</head>
<body>
<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>
<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" 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="登录" class="btn btn-primary"/>
</form>
</div>
</div>
</body>
</html>

home.html

<!DOCTYPE html>
<html xmlns:th="http://www.">
<head>
<meta charset="UTF-8"/>
<title>首页</title>
<link th:href="@{css/bootstrap.min.css}" rel="stylesheet"/>
<style type="text/css">
body{
padding-top:50px;
}
.starter-template{
padding:40px 15px;
text-align:center;
}
</style>
</head>
<body>
<div class="container">
<div class="starter-template">
<h1 th:text="${msg.title}"></h1>
<p class="bg-primary" th:text="${msg.content}"></p>
<div sec:authorize="hasRole('ROLE_ADMIN')">
<p class="bg-info" th:text="${msg.etraInfo}"></p>
</div>
<div sec:authorize="hasRole('ROLE_USER')">
<p class="bg-info">无更多信息显示</p>
</div>
<form th:action="@{/logout}" method="post">
<input type="submit" class="btn-primary" value="注销"/>
</form>
</div>
</div>
</body>
</html>

创建控制器Controller:

package com.springboot.security.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.springboot.security.entity.Msg;

@Controller
public class HomeController {

@RequestMapping("/")
public String index(Model model){
Msg msg = new Msg("测试标题", "测试内容", "额外信息,只对管理员展示");
model.addAttribute("msg", msg);
return "home";
}
}

创建执行类Main

package com.springboot.security;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {

public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}

运行,访问localhost:8080,会自动跳转到登陆页面:

微儿博客

使用错误的账号登录:

微儿博客

使用管理员账号登录:

admin.png

使用普通用户账号登录:

微儿博客

点击注销:

微儿博客

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约