在SpringBoot项目中使用SpringSecurity权限认证框架
2017-12-21 15:28
1051 查看
当前两大权限认证框架:shiro和Spring Security
SpringBoot版本:1.5.8
1.在SpringBoot中欲使用Spring Security,首先需要添加依赖:
<!--声明使用Spring security的依赖-->
<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>
2.在Application的Properties文件中,配置:
#Spring Security config
logging.level.org.springframework.security=info
3.写一个Security的Java配置类:
package com.kgoos.app.configure;
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;
@Configuration
public class
WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService() {
//2
return new
SysUserServiceImpl();
}
@Override
protected void
configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(customUserService());
}
@Override
protected void
configure(HttpSecurity http) throws
Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and()
.logout().permitAll();
}
}
在SpringMVC中也添加配置:
@Configuration
public class
MyWebConfig extends
WebMvcConfigurerAdapter {
@Override
public void
addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
4.准备SpringSecurity认证需要的两个实体类:SysRole和SysUser
import lombok.Getter;
import
lombok.Setter;
import
javax.persistence.Entity;
import
javax.persistence.GeneratedValue;
import
javax.persistence.Id;
import
java.io.Serializable;
/**
* Description:This PO is used for system auth :Spring Security
*
@author
dbdu
*
@date
17-12-21 上午9:34
*/
@Entity
@Getter@Setter
public class
SysRole implements
Serializable { //注意此处要实现序列化接口,否则终端执行会出错!
@Id
@GeneratedValue
private
Long id;
private
String name;
}
------------------------------------------
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import
javax.persistence.CascadeType;
import
javax.persistence.Entity;
import
javax.persistence.FetchType;
import
javax.persistence.GeneratedValue;
import
javax.persistence.Id;
import
javax.persistence.ManyToMany;
import
lombok.Getter;
import
lombok.Setter;
import
org.springframework.security.core.GrantedAuthority;
import
org.springframework.security.core.authority.SimpleGrantedAuthority;
import
org.springframework.security.core.userdetails.UserDetails;
@Entity
@Getter@Setter
public class
SysUser
implements
UserDetails { //1
private static final long
serialVersionUID
= 1L;
@Id
@GeneratedValue
private
Long id;
private
String username;
private
String password; //当然若是实际项目中使用,可能会有其他更多的属性.
@ManyToMany(cascade = {CascadeType.REFRESH},
fetch = FetchType.EAGER)
private
List<SysRole> roles;
@Override
public
Collection<? extends
GrantedAuthority> getAuthorities() {
//2
List<GrantedAuthority> auths =
new ArrayList<GrantedAuthority>();
List<SysRole> roles =
this.getRoles();
for
(SysRole role : roles) {
auths.add(new
SimpleGrantedAuthority(role.getName()));
}
return
auths;
}
@Override
public boolean
isAccountNonExpired() {
return true;
}
@Override
public boolean
isAccountNonLocked() {
return true;
}
@Override
public boolean
isCredentialsNonExpired() {
return true;
}
@Override
public boolean
isEnabled() {
return true;
}
}
5.准备实体对应的repository和Service
import com.kgoos.app.entity.SysUser;
import org.springframework.data.jpa.repository.JpaRepository;
public interface
SysUserRepository
extends
JpaRepository<SysUser, Long> {
SysUser findByUsername(String username);
}
---------------------------------------
import com.kgoos.app.entity.SysUser;
import
com.kgoos.app.repository.SysUserRepository;
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;
@Service
public class
SysUserServiceImpl implements
ISysUserService { //1
@Autowired
SysUserRepository
userRepository;
@Override
public
UserDetails loadUserByUsername(String username) {
//2
SysUser user =
userRepository.findByUsername(username);
if(user ==
null){
throw new
UsernameNotFoundException("用户名不存在");
}
return
user; //3
}
}
/**
* Description:此处继承仅是为了让代码看起来更加规范而已
* Created at:2017-12-21 10:12,
* by dbdu
*/
public interface
ISysUserService extends
UserDetailsService {}
6.向数据表中插入基本的数据:
insert into SYS_USER (id,username, password) values (1,'dbdu', 'dbdu');
insert into SYS_USER (id,username, password) values (2,'dusuanyun', 'dusuanyun');
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);
7.注意login和logout的url是固定的,为/login和/logout,不需要专门为这两个url写控制器!!
8.准备login.html和home.html的thymeleaf文件放置在,resources--templates目录下.
9.详细信息,参考KGoos项目的security_test_branch分支,此分支配置了此框架的认证方式.
疑问1:如何根据角色不同,区分什么是admin的,什么是普通用户的?
解答:
方式一:使用thymeleaf有方式可以判断角色
A.先引入命名空间:<html
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
B.使用hasRole('ROLE_ADMIN')"来判断角色:
<div
sec:authorize="hasRole('ROLE_ADMIN')">
<p
class="bg-info"
th:text="${msg.etraInfo}"></p>
</div>
方式二:使用异步Ajax的方式
如果前端需要角色信息来决定显示什么页面,可以考虑提供控制器将用户信息以Json的方式给前端!
疑问2:如何添加用户?
解决:利用Hibernate的映射关系存储关联关系!
疑问3:如何使用密码的密文? ---现在存储的是明文
解决:
第一步:自己定义一个密码编码解码的类实现PasswordEncoder接口
/**
* Description: 这个类是专为使用SpringSecurity认证框架设计的,用户处理密码是明码还是密码的问题!
* Created at:2017-12-21 14:18,
* by dbdu
*/
public class
MD5PasswordEncoder implements
PasswordEncoder {
@Override
public
String encode(CharSequence charSequence) {
return
MD5Util.encode((String) charSequence);
}
@Override
public boolean
matches(CharSequence rawPassword, String encodedPassword) {
if
(null
!= encodedPassword && encodedPassword.equals(encode(rawPassword))) {
return true;
}
return false;
}
}
第二步:在WebSecurityConfig类中,增加自定义的编码解码器,例如:
@Configuration
public class
WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService() {
//2
return new
SysUserServiceImpl();
}
@Override
protected void
configure(AuthenticationManagerBuilder auth)
throws Exception {
//指定密码的编码和解码方式:MD5PasswordEncoder
auth.userDetailsService(customUserService()).passwordEncoder(new
MD5PasswordEncoder());
//auth.userDetailsService(sysUserService);
}
@Override
protected void
configure(HttpSecurity http)
throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and()
.logout().permitAll();
}
}
疑问4:如何将登录的用户,用户名显示在页面上,其实就是如何获取已经登录成功的用户的信息
解决:没有测试过
A.JSP的方式:principal 用户的基本信息对象
B.Thymeleaf的方式:
方式一:使用表达式实用程序对象
该#authentication对象可以很容易地使用,就像这样:
<
div
th:text
= “ $ {#authentication.name} ” > 认证对象的“name”属性的值应该出现在这里。 </
div >
方式二:使用sec:authentication属性相当于使用#authentication对象,但使用自己的属性:
<
div
sec:authentication
= “ name ” > 认证对象的“name”属性的值应该出现在这里。 </
div >
更多的内容参见:https://github.com/thymeleaf/thymeleaf-extras-springsecurity
英语不好的朋友可以用谷歌浏览器右键翻译
C.自己的思路:
登录成功后,发请求,然后将请求到的数据直接存到session会话里,写一个监听器session注销的时候,清除保存在session里的数据,当然你要是不管它好像也没什么问题.
参考资料:
A.<<JavaEE开发的颠覆者-SpringBoot实战>>,第九章第一节
B.<<Spring实战第四版中文版>>,第九章
C.参考链接:https://github.com/thymeleaf/thymeleaf-extras-springsecurity
SpringBoot版本:1.5.8
1.在SpringBoot中欲使用Spring Security,首先需要添加依赖:
<!--声明使用Spring security的依赖-->
<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>
2.在Application的Properties文件中,配置:
#Spring Security config
logging.level.org.springframework.security=info
3.写一个Security的Java配置类:
package com.kgoos.app.configure;
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;
@Configuration
public class
WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService() {
//2
return new
SysUserServiceImpl();
}
@Override
protected void
configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(customUserService());
}
@Override
protected void
configure(HttpSecurity http) throws
Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and()
.logout().permitAll();
}
}
在SpringMVC中也添加配置:
@Configuration
public class
MyWebConfig extends
WebMvcConfigurerAdapter {
@Override
public void
addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
4.准备SpringSecurity认证需要的两个实体类:SysRole和SysUser
import lombok.Getter;
import
lombok.Setter;
import
javax.persistence.Entity;
import
javax.persistence.GeneratedValue;
import
javax.persistence.Id;
import
java.io.Serializable;
/**
* Description:This PO is used for system auth :Spring Security
*
@author
dbdu
*
@date
17-12-21 上午9:34
*/
@Entity
@Getter@Setter
public class
SysRole implements
Serializable { //注意此处要实现序列化接口,否则终端执行会出错!
@Id
@GeneratedValue
private
Long id;
private
String name;
}
------------------------------------------
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import
javax.persistence.CascadeType;
import
javax.persistence.Entity;
import
javax.persistence.FetchType;
import
javax.persistence.GeneratedValue;
import
javax.persistence.Id;
import
javax.persistence.ManyToMany;
import
lombok.Getter;
import
lombok.Setter;
import
org.springframework.security.core.GrantedAuthority;
import
org.springframework.security.core.authority.SimpleGrantedAuthority;
import
org.springframework.security.core.userdetails.UserDetails;
@Entity
@Getter@Setter
public class
SysUser
implements
UserDetails { //1
private static final long
serialVersionUID
= 1L;
@Id
@GeneratedValue
private
Long id;
private
String username;
private
String password; //当然若是实际项目中使用,可能会有其他更多的属性.
@ManyToMany(cascade = {CascadeType.REFRESH},
fetch = FetchType.EAGER)
private
List<SysRole> roles;
@Override
public
Collection<? extends
GrantedAuthority> getAuthorities() {
//2
List<GrantedAuthority> auths =
new ArrayList<GrantedAuthority>();
List<SysRole> roles =
this.getRoles();
for
(SysRole role : roles) {
auths.add(new
SimpleGrantedAuthority(role.getName()));
}
return
auths;
}
@Override
public boolean
isAccountNonExpired() {
return true;
}
@Override
public boolean
isAccountNonLocked() {
return true;
}
@Override
public boolean
isCredentialsNonExpired() {
return true;
}
@Override
public boolean
isEnabled() {
return true;
}
}
5.准备实体对应的repository和Service
import com.kgoos.app.entity.SysUser;
import org.springframework.data.jpa.repository.JpaRepository;
public interface
SysUserRepository
extends
JpaRepository<SysUser, Long> {
SysUser findByUsername(String username);
}
---------------------------------------
import com.kgoos.app.entity.SysUser;
import
com.kgoos.app.repository.SysUserRepository;
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;
@Service
public class
SysUserServiceImpl implements
ISysUserService { //1
@Autowired
SysUserRepository
userRepository;
@Override
public
UserDetails loadUserByUsername(String username) {
//2
SysUser user =
userRepository.findByUsername(username);
if(user ==
null){
throw new
UsernameNotFoundException("用户名不存在");
}
return
user; //3
}
}
/**
* Description:此处继承仅是为了让代码看起来更加规范而已
* Created at:2017-12-21 10:12,
* by dbdu
*/
public interface
ISysUserService extends
UserDetailsService {}
6.向数据表中插入基本的数据:
insert into SYS_USER (id,username, password) values (1,'dbdu', 'dbdu');
insert into SYS_USER (id,username, password) values (2,'dusuanyun', 'dusuanyun');
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);
7.注意login和logout的url是固定的,为/login和/logout,不需要专门为这两个url写控制器!!
8.准备login.html和home.html的thymeleaf文件放置在,resources--templates目录下.
9.详细信息,参考KGoos项目的security_test_branch分支,此分支配置了此框架的认证方式.
疑问1:如何根据角色不同,区分什么是admin的,什么是普通用户的?
解答:
方式一:使用thymeleaf有方式可以判断角色
A.先引入命名空间:<html
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
B.使用hasRole('ROLE_ADMIN')"来判断角色:
<div
sec:authorize="hasRole('ROLE_ADMIN')">
<p
class="bg-info"
th:text="${msg.etraInfo}"></p>
</div>
方式二:使用异步Ajax的方式
如果前端需要角色信息来决定显示什么页面,可以考虑提供控制器将用户信息以Json的方式给前端!
疑问2:如何添加用户?
解决:利用Hibernate的映射关系存储关联关系!
疑问3:如何使用密码的密文? ---现在存储的是明文
解决:
第一步:自己定义一个密码编码解码的类实现PasswordEncoder接口
/**
* Description: 这个类是专为使用SpringSecurity认证框架设计的,用户处理密码是明码还是密码的问题!
* Created at:2017-12-21 14:18,
* by dbdu
*/
public class
MD5PasswordEncoder implements
PasswordEncoder {
@Override
public
String encode(CharSequence charSequence) {
return
MD5Util.encode((String) charSequence);
}
@Override
public boolean
matches(CharSequence rawPassword, String encodedPassword) {
if
(null
!= encodedPassword && encodedPassword.equals(encode(rawPassword))) {
return true;
}
return false;
}
}
第二步:在WebSecurityConfig类中,增加自定义的编码解码器,例如:
@Configuration
public class
WebSecurityConfig extends
WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService() {
//2
return new
SysUserServiceImpl();
}
@Override
protected void
configure(AuthenticationManagerBuilder auth)
throws Exception {
//指定密码的编码和解码方式:MD5PasswordEncoder
auth.userDetailsService(customUserService()).passwordEncoder(new
MD5PasswordEncoder());
//auth.userDetailsService(sysUserService);
}
@Override
protected void
configure(HttpSecurity http)
throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and()
.logout().permitAll();
}
}
疑问4:如何将登录的用户,用户名显示在页面上,其实就是如何获取已经登录成功的用户的信息
解决:没有测试过
A.JSP的方式:principal 用户的基本信息对象
B.Thymeleaf的方式:
方式一:使用表达式实用程序对象
该#authentication对象可以很容易地使用,就像这样:
<
div
th:text
= “ $ {#authentication.name} ” > 认证对象的“name”属性的值应该出现在这里。 </
div >
方式二:使用sec:authentication属性相当于使用#authentication对象,但使用自己的属性:
<
div
sec:authentication
= “ name ” > 认证对象的“name”属性的值应该出现在这里。 </
div >
更多的内容参见:https://github.com/thymeleaf/thymeleaf-extras-springsecurity
英语不好的朋友可以用谷歌浏览器右键翻译
C.自己的思路:
登录成功后,发请求,然后将请求到的数据直接存到session会话里,写一个监听器session注销的时候,清除保存在session里的数据,当然你要是不管它好像也没什么问题.
参考资料:
A.<<JavaEE开发的颠覆者-SpringBoot实战>>,第九章第一节
B.<<Spring实战第四版中文版>>,第九章
C.参考链接:https://github.com/thymeleaf/thymeleaf-extras-springsecurity
相关文章推荐
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(二)
- 使用springboot框架写项目打包jar发布后读取项目下静态文件异常
- 在spring boot项目中配置权限框架shiro
- 在前后端分离的SpringBoot项目中集成Shiro权限框架
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(一)
- 使用Spring Boot框架maven项目新建后启动失败, 提示Unregistering JMX-exposed beans on shutdown
- SpringBoot项目中使用日志框架log4j——为什么使用日志(一)
- springboot+angular项目 使用token方式进行权限验证
- Spring boot框架项目,使用maven命令将配置文件打包到jar包外,项目运行读取jar外配置文件
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(六)
- 微服务框架(一)--Eclipse使用maven创建spring boot项目
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
- 在前后端分离的SpringBoot项目中集成Shiro权限框架
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题的解决方法
- 在spring boot项目中配置权限框架shiro
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
- 架构实战项目心得(七):使用SpringBoot+Dubbo+Mybatisplus+Oracle搭建后台项目框架(二)
- 架构实战项目心得(七):使用SpringBoot+Dubbo+Mybatisplus+Oracle搭建后台项目框架(一)
- SpringBoot中使用Springsecurity实现权限控制
- (4)Spring Boot使用别的json解析框架【从零开始学Spring Boot】