SpringBoot 集成Spring security
Spring security作为一种安全框架,使用简单,能够很轻松的集成到springboot项目中,下面讲一下如何在SpringBoot中集成Spring Security.使用gradle项目管理工具。
准备数据,
CREATE TABLE `user` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`roles` varchar(200) DEFAULT 'USER',
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; insert into `user` values(0,'admin','admin','SUPER,role'); //给不同个用户配置不同的权限
insert into `user` values(1,'role','role','role');
1:配置buildgradle,添加spring boot插件和spring security
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath('org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE')
}
}
group "com.li"
version "1.0-SNAPSHOT"
apply plugin: "java" //java 插件
apply plugin: "org.springframework.boot" //spring boot 插件
apply plugin: "io.spring.dependency-management"
apply plugin: "application" //应用
mainClassName = "com.li.SpringBootShrioApplication"
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-activemq",
"org.springframework.boot:spring-boot-starter-test",
"org.springframework.boot:spring-boot-starter-cache",
"org.springframework.boot:spring-boot-devtools",
"mysql:mysql-connector-java:5.1.35",
'org.apache.commons:commons-lang3:3.4',
'org.apache.commons:commons-pool2',
"org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.0",
'org.apache.logging.log4j:log4j-core:2.7',
'org.springframework.boot:spring-boot-starter-security',
'org.springframework.boot:spring-boot-starter-thymeleaf',
'org.thymeleaf.extras:thymeleaf-extras-springsecurity4', //thymeleaf模板,集成 springsecurity4
'net.sourceforge.nekohtml:nekohtml' ) testCompile group: 'junit', name: 'junit', version: '4.12' }
2:配置spring boot, application.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springsecurity
username: root
password: 1367356
thymeleaf:
mode: LEGACYHTML5
cache: false devtools:
restart:
enabled: true
server:
port: 8081
mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml #Mapper所在的配置文件路径,进行扫描
config-location: classpath:mybatis/mybatis-config.xml # mybaits-config文件
3:配置Spring Security
WebSecurityConfig.java 继承 WebSecurityConfigurerAdapter.
当访问项目时,安全管理器按照配置进行拦截,验证通过才能访问Controller相应的路径。
package com.li.security; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Autowired
MyUserDetailsService myUserDetailsService; @Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(myUserDetailsService);
authenticationProvider.setPasswordEncoder(this.bCryptPasswordEncoder());
return authenticationProvider;
} @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService).passwordEncoder(this.bCryptPasswordEncoder());
} @Override
protected void configure(HttpSecurity http) throws Exception {
// String[] s=null;
http.csrf().disable()
.authorizeRequests()
.antMatchers("/user/settings").authenticated() // order matters
.antMatchers("/", "/js/**", "/css/**","/avatar/**", "/images/**", "/fonts/**", "/bootstrap-select/**", "/bootstrap-datetimepicker/**", "/custom/**", "/daterangepicker/**", "/chartjs/**").permitAll() // these paths are configure not to require any authentication
.antMatchers("/post/**").permitAll() // all posts are allowed to be viewed without authentication
// .antMatchers("/user/**").permitAll() // all user profiles are allowed to be viewed without authentication
.antMatchers("/category/**").permitAll() // all categories are allowed to be viewed without authentication
.antMatchers("/user/registration").permitAll()
.antMatchers("/avatar/**").permitAll() // temp
.antMatchers("/visitor/**").permitAll() // temp
// .antMatchers("/admin/**").hasAnyRole("SUPER","USER")
// .antMatchers("/admin/**").
// .antMatchers("/admin/**").hasAnyRole(s)
.anyRequest().authenticated() // every request requires the user to be authenticated
.and()
.formLogin()
.loginPage("/user/login")
.permitAll() // login URL can be accessed by anyone
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/?logout")
.permitAll();
}
}
验证:对访问用户进行验证
package com.li.security; import com.li.dao.User;
import com.li.service.UserService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import java.util.ArrayList;
import java.util.List; @Service
public class MyUserDetailsService implements UserDetailsService{ Logger logger = LogManager.getLogger(MyUserDetailsService.class);
@Autowired
private UserService userService; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = this.userService.findUserByUserName(username);
logger.debug(user.getUserName()+"密码"+user.getPassword());
if(null == user) {
throw new UsernameNotFoundException("Can't find user by username: " + username);
} List<SimpleGrantedAuthority> grantedAuthorities = new ArrayList<>();
// grant roles to user
for (String role : user.getRolesSet()) {
logger.debug(role);
grantedAuthorities.add(new SimpleGrantedAuthority(role)); //认证
}
// user.setGrantedAuthorities(authorities); //用于登录时 @AuthenticationPrincipal 标签取值
return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(), grantedAuthorities); //角色认证
}
}
4: Controller ,Service,Dao层编写
验证通过,Controller对相应的http处理。可以在每个http上面指定相应的访问权限
package com.li.controller; import com.li.dao.User;
import com.li.service.UserService;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.config.ResourceNotFoundException;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import javax.validation.Valid;
import java.util.Map; @Controller
public class UserController { @Autowired
UserService userService; @RequestMapping(value = "/", method = RequestMethod.GET)
public String login() {
System.out.println("home");
return "forum/home";
} @RequestMapping(value = "/user/login", method = RequestMethod.GET)
public String displayLoginPage(Model model) {
System.out.println("进入");
model.addAttribute("title", "用户登陆");
return "forum/user-login"; //登录界面,验证没通过。
} /**
* 用户注册
* @param model
* @return
*/
@RequestMapping(value = "/user/registration", method = RequestMethod.GET)
public String showRegistrationPage(Model model) {
System.out.println("registrationGet");
model.addAttribute("userDto", new User());
return "forum/user-registration"; //注册页面
} @RequestMapping(value = "/user/registration", method = RequestMethod.POST) //提交注册
public String registerNewUser(@ModelAttribute("userDto") User user,BindingResult bindingResult,
Model model, HttpServletRequest request) {
System.out.println("registrationPost");
Map<String, Object> attributes = this.userService.registerUserAccount(user);
model.addAllAttributes(attributes);
return "forum/user-registration-result";
} @PreAuthorize("hasAuthority('SUPER')") //需要SUPER用户才能通过该路径,第一步通过配置验证,没有用户登录,将会拦截,让用户登录,登录成功,访问该路径时进行角色验证。
@RequestMapping(value = "/admin/admin", method = RequestMethod.GET)
public String deletePost() {
return "admin/admin";
} }
Service
package com.li.service; import com.li.dao.User; import javax.servlet.http.HttpServletRequest;
import java.util.Map; public interface UserService {
public User findUserByUserName(String userName);
public Map<String, Object> registerUserAccount(User user);
}
SeriviceImpl,对用户密码加密存储,
package com.li.service.impl; import com.li.dao.User;
import com.li.dao.mapper.UserMapper;
import com.li.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.UUID; @Service
public class UserServiceImpl implements UserService{ @Autowired
BCryptPasswordEncoder bCryptPasswordEncoder; @Autowired
UserMapper userMapper; @Override
public User findUserByUserName(String userName) {
return userMapper.findByUserName(userName);
} @Override
public Map<String, Object> registerUserAccount(User userDto) {
Map<String, Object> attributes = new HashMap<>(); // save newly registered user
User user = new User(); user.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); //保存时应该将密码编码
user.setUserName(userDto.getUserName());
// user.activated(true);
user.setRoles("USER");
// user.setConfirmationToken(UUID.randomUUID().toString()); // save new user and get number of affected row
// logger.debug("用户注册");
int affectedRow = userMapper.save(user);// populate attributes
String registrationResult = affectedRow == 1 ? "success" : "failure";
attributes.put("userRegistrationResult", registrationResult);
return attributes;
}
}
DaoMapper
package com.li.dao.mapper; import com.li.dao.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; @Mapper
public interface UserMapper {
public User findByUserName(String username); public int save(@Param("user") User user);
}
普通User类
package com.li.dao; import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set; /**
* 实验室网站用户
*/
public class User {
public int id;
public String userName;
public String password;
public String roles; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} 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;
} public String getRoles() {
return roles;
} public void setRoles(String roles) {
this.roles = roles;
} public Set<String> getRolesSet() { //获取用户权限
if (null == roles) {
return null;
}
return Collections.unmodifiableSet(
new HashSet<String>(Arrays.asList(getRoles().split(","))));
} public void addRole(String role) {
String currRoles = this.getRoles();
if (null == currRoles || this.getRoles().contains(role)) {
return;
}
this.setRoles(currRoles + "," + role);
} @Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", roles='" + roles + '\'' +
'}';
}
}
5:编写项目的前台页面,static文件夹下面,不同权限的页面放到不同种类下面
SpringBoot 集成Spring security的更多相关文章
- SpringBoot集成Spring Security入门体验
一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...
- SpringBoot集成Spring Security(7)——认证流程
文章目录 一.认证流程 二.多个请求共享认证信息 三.获取用户认证信息 在前面的六章中,介绍了 Spring Security 的基础使用,在继续深入向下的学习前,有必要理解清楚 Spring Sec ...
- SpringBoot集成Spring Security(6)——登录管理
文章目录 一.自定义认证成功.失败处理 1.1 CustomAuthenticationSuccessHandler 1.2 CustomAuthenticationFailureHandler 1. ...
- SpringBoot集成Spring Security(5)——权限控制
在第一篇中,我们说过,用户<–>角色<–>权限三层中,暂时不考虑权限,在这一篇,是时候把它完成了. 为了方便演示,这里的权限只是对角色赋予权限,也就是说同一个角色的用户,权限是 ...
- SpringBoot集成Spring Security(4)——自定义表单登录
通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...
- SpringBoot集成Spring Security(2)——自动登录
在上一章:SpringBoot集成Spring Security(1)——入门程序中,我们实现了入门程序,本篇为该程序加上自动登录的功能. 文章目录 一.修改login.html二.两种实现方式 2. ...
- SpringBoot集成Spring Security
1.Spring Security介绍 Spring security,是一个强大的和高度可定制的身份验证和访问控制框架.它是确保基于Spring的应用程序的标准 --来自官方参考手册 Spring ...
- SpringBoot集成Spring Security(1)——入门程序
因为项目需要,第一次接触 Spring Security,早就听闻 Spring Security 功能强大但上手困难,学习了几天出入门道,特整理这篇文章希望能让后来者少踩一点坑(本文附带实例程序,请 ...
- SpringBoot集成Spring Security(授权与认证)
⒈添加starter依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifact ...
随机推荐
- mysql数据库使用mysqldump工具针对一个数据库备份,使用--databases选项与不使用该参数的区别
需求描述: 今天在做mysqldump备份某个数据库的试验,在备份某个数据库的时候可以使用 --databases参数,也可以直接进行某个数据库的备份,那么这里记录下两者的区别 操作过程: 1.使用- ...
- when an event of selector will be fired
OP_READ Operation-set bit for read operations. Suppose that a selection key's interest set contains ...
- swift - UISegmentedControl 和 UIWebView 的用法
这两个用法比较简单: 具体代码如下: 一.UISegmentedControl 1.UISegmentedControl的声明 var segment = UISegmentedControl() 2 ...
- 添加app第一次启动页面
一.添加几个成员变量 @interface hDisplayView ()<UIScrollViewDelegate> { UIScrollView *_bigScrollView; NS ...
- Android 4.0 Tabhost图标显示不出来
安卓4.0会有这个问题,修改Manifest.xml里面的Theme,找到System Resources,里面有Theme.black,选这个就行了.剩下自己要改背景色什么的这个还是比较easy的吧 ...
- C#中的抽象类与重写
今天的我们学习了好多,最初上午学习了文件流的方法,老师告诉我们是选修,可能以后不怎么用吧,但是还是想学下,似乎用个小程序读写文件很快地节奏,所以有点小兴趣学习,明天我再看看啦!今天之后学习了多态,继承 ...
- 使用类/结构体时关于ZeroMomery用法错误
今天同事在写了如下结构体: typedef struct _tagInfo { std::list<int> lst; std::vector<int> nVec; } INF ...
- iOS 自动布局 Autolayout 优先级的使用
一.约束的优先级 0.屏幕适配 发展历程 代码计算frame -> autoreszing(父控件和子控件的关系) -> autolayout(任何控件都可以产生关系) -> siz ...
- struts2基础---->自定义类型转换器
这一章,我们开始struts2中自定义类型转换器的学习. 自定义类型转换器
- C++,一些常用的知识点
用typedef定义数组.指针.结构等类型将带来很大的方便,不仅使程序书写简单而且使意义更为明确,因而增强了可读 性. C++中是用关键字typedef定义一个标识符来代表一种数据类型,该标识符可以象 ...