springboot综合案例第三课
springboot综合案例第三课
什么是SpringSecurity
Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。
(/) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别
是使用领先的J2EE解决方案-Spring框架开发的企业软件项目。人们使用Spring Security有很多种原因,不过通常吸
引他们的是在J2EE Servlet规范或EJB规范中不到典型企业应用场景的解决方案。特别要指出的是他们不能再
WAR 或 EAR 级别进行移植。这样,如果你更换服务器环境,就要,在新的目标环境进行大量的工作,对你的应用
系统进行重新配置安全。使用Spring Security 解决了这些问题,也为你提供很多有用的,完全可以指定的其他安
全特性。安全包括两个主要操作。
- “认证”,是为用户建立一个他所声明的主体。主题一般式指用户,设备或可以在你系统中执行动作的其他系
统。(简单来说:系统认为用户是否能登录)
- “授权”,指的是一个用户能否在你的应用中执行某个操作,在到达授权判断之前,身份的主题已经由身份验证
过程建立了。(简单来说:系统判断用户是否有权限去做某些事情)
这些概念是通用的,不是Spring Security特有的。在身份验证层面,Spring Security广泛支持各种身份验证模式,
这些验证模型绝大多数都由第三方提供,或则正在开发的有关标准机构提供的,例如 Internet Engineering Task
Force.作为补充,Spring Security 也提供了自己的一套验证功能。
Spring Security 目前支持认证一体化如下认证技术: HTTP BASIC authentication headers (一个基于IEFT RFC 的
标准) HTTP Digest authentication headers (一个基于IEFT RFC 的标准) HTTP X.509 client certi?cate exchange
(一个基于IEFT RFC 的标准) LDAP (一个非常常见的跨平台认证需要做法,特别是在大环境) Form-based
authentication (提供简单用户接口的需求) OpenID authentication Computer Associates Siteminder JA-SIG
Central Authentication Service (CAS,这是一个流行的开源单点登录系统) Transparent authentication context
propagation for Remote Method Invocation and HttpInvoker (一个Spring远程调用协议)
-- 用户表
CREATE TABLE users(
id VARCHAR(2) PRIMARY KEY,
email VARCHAR(50) UIQUE OT ULL,
username VARCHAR(50),
PASSWORD VARCHAR(100),
phoneum VARCHAR(20),
STATUS IT
);
-- 角表
CREATE TABLE role(
id VARCHAR(2) PRIMARY KEY,
roleame VARCHAR(50) ,
roleDesc VARCHAR(50)
);
-- 用户角关联表
CREATE TABLE users_role(
userId VARCHAR(2),
roleId VARCHAR(2),
PRIMARY KEY(userId,roleId),
FOREIG KEY (userId) REFERECES users(id),
FOREIG KEY (roleId) REFERECES role(id)
);
-- 资源权限表
CREATE TABLE permission(
id VARCHAR(2) PRIMARY KEY,
permissioname VARCHAR(50) ,
url VARCHAR(50)
);
-- 角权限关联表
CREATE TABLE role_permission(
permissionId VARCHAR(2),
roleId VARCHAR(2),
PRIMARY KEY(permissionId,roleId),
FOREIG KEY (permissionId) REFERECES permission(id),
FOREIG KEY (roleId) REFERECES role(id)
);
创建UserInfo
代码语言:javascript代码运行次数:0运行复制@Data
public class UserInfo {
private String id;
private String username;
private String email;
private String password;
private String phoneum;
private int status;
private String statusStr;
private List<Role> roles;
}
创建Role
代码语言:javascript代码运行次数:0运行复制@Data
public class Role {
private String id;
private String roleame;
private String roleDesc;
private List<Permission> permissi;
private List<UserInfo> users;
}
创建Permission
代码语言:javascript代码运行次数:0运行复制@Data
public class Permission {
private String id;
private String permissioname;
private String url;
private List<Role> roles;
}
在Spring Security中如果想要使用数据进行认证操作,有很多种操作方式,这里我们介绍使用UserDetails、
UserDetailsService来完成操作。
- UserDetails
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountonExpired();
boolean isAccountonLocked();
boolean isCredentialsonExpired();
boolean isEnabled();
}
UserDatails是一个接口,我们可以认为UserDetails作用是于封装当前进行认证的用户信息,但由于其是一个
接口,所以我们可以对其进行实现,也可以使用Spring Security提供的一个UserDetails的实现类User来完成
操作,Ctrl+Alt+B 查接口实现类
以下是User类的部分代码
代码语言:javascript代码运行次数:0运行复制public class User implements UserDetails, CredentialsContainer {
private String password;
private final String username;
private final Set<GrantedAuthority> authorities;
private final boolean accountonExpired; //帐户是否过期
private final boolean accountonLocked; //帐户是否锁定
private final boolean credentialsonExpired; //认证是否过期
private final boolean enabled; //帐户是否可用
}
- UserDetailsService
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameotFoundException;
}
上面将UserDetails与UserDetailsService做了一个简单的介绍,那么我们具体如何完成Spring Security的数据库认
证操作,我们通过用户管理中用户登录来完成Spring Security的认证操作。
添加依赖
代码语言:javascript代码运行次数:0运行复制<!--SpringSecurity-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Spring Security配置类
代码语言:javascript代码运行次数:0运行复制package cn.;
import cn.yanqi.service.UserService;
import org.annotation.Bean;
import org.annotation.Configuration;
import org.springframework.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.EnableGlobalMethodSecurity;
import org.springframework.annotation.web.builders.HttpSecurity;
import org.springframework.annotation.EnableWebSecurity;
import org.springframework.annotation.WebSecurityConfigurerAdapter;
import org.springframework.bcrypt.BCryptPasswordEncoder;
import org.springframework.password.PasswordEncoder;
import javax.annotation.Resource;
// @EnableGlobalMethodSecurity(jsr250Enabled = true) //开启jsr250注解
// @EnableGlobalMethodSecurity(securedEnabled = true) //开启secured注解
// @EnableGlobalMethodSecurity(prePostEnabled = true) //开启表达式注解
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
//自定义表单登录页面
http.formLogin()
//指定登录页面
.loginPage("/to/login")
//指定登录请求
.loginProcessingUrl("/login")
.usernameParameter("username")
.passwordParameter("password")
.successForwardUrl("/to/index")
.failureUrl("/to/failer")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/to/login")
.invalidateHttpSession(true) //是否清除session
.and()
//权限配置
.authorizeRequests()
//放行 登录页面
.antMatchers("/to/login","/to/failer").permitAll()
//放开 静态资源
.antMatchers("/css/**","/img/**","/js/**","/plugins/**").permitAll()
//其他 资源需要登录后访问
.anyRequest().authenticated()
.and()
//禁用csrf
.csrf().disable();
//没有权限
().accessDeniedPage("/to/40");
}
//认证的数据需要使用自定义的UserDetailsService
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
编写UserService
代码语言:javascript代码运行次数:0运行复制package cn.yanqi.service;
import org.springframework.userdetails.UserDetailsService;
//继承 UserDetailsService 重写loadUserByUsername 完成认证
public interface UserService extends UserDetailsService {
}
代码语言:javascript代码运行次数:0运行复制import cn.UserMapper;
import cn.pojo.Role;
import cn.pojo.UserInfo;
import cn.service.UserService;
import org.springframework.authority.SimpleGrantedAuthority;
import org.springframework.userdetails.User;
import org.springframework.userdetails.UserDetails;
import org.springframework.userdetails.UsernameotFoundException;
import org.springframework.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private PasswordEncoder passwordEncoder;
/**
* 认证--查询用户
* @param s
* @return
* @throws UsernameotFoundException
*/
@Override
public UserDetails loadUserByUsername(String s) throws UsernameotFoundException {
UserInfo userInfo = this.userMapper.findUserByUserame(s);
User user = new User(
userInfo.getUsername(),
userInfo.getPassword(),
userInfo.getStatus() == 0 ? false : true,//校验用户是否开启
true, //帐号是否过期 不过期
true, //证号 不过期
true, //帐号 不锁定
getAuthority(userInfo.getRoles()));
println("用户:"+userInfo.getUsername());
println("=======================");
return user;
}
/**
* 认证--查询用户对应的角
*/
private List<SimpleGrantedAuthority> getAuthority(List<Role> roles) {
List<SimpleGrantedAuthority> list = new ArrayList<>();
for(Role role : roles){
println("对应角:"+role.getRoleame());
list.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleame()));
}
return list;
}
}
编写UserMapper
代码语言:javascript代码运行次数:0运行复制public interface UserMapper {
/**
* 通过用户名查询用户
* @param s
* @return
*/
UserInfo findUserByUserame(String s);
}
编写UserMapper.xml
代码语言:javascript代码运行次数:0运行复制<!--登录认证:通过用户名查询用户-->
<resultMap id="userresultMap" type="UserInfo" autoMapping="true">
<id property="id" column="id"/>
<collection property="roles" ofType="Role" javaType="List" autoMapping="true">
<id property="id" column="rid"/>
</collection>
</resultMap>
<select id="findUserByUserame" resultMap="userresultMap">
SELECT
*,r.id rid
FROM
users u,
role r,
users_role ur
WHERE
u.id = ur.userId
AD
r.id = ur.roleId
AD
u.username = #{s}
</select>
注意事项:如果登录认证提交出现405,是因为通用页面跳转是@GetMapping, Security的登录后台跳转需要post请求
把通用页面跳转改为@RequestMapping(“{page}”)即可
测试
登录认证-把users表中的status状态修改 0和1进行测试
Spring Security配置类
代码语言:javascript代码运行次数:0运行复制// @EnableGlobalMethodSecurity(jsr250Enabled = true) //开启jsr250注解
// @EnableGlobalMethodSecurity(securedEnabled = true) //开启secured注解
// @EnableGlobalMethodSecurity(prePostEnabled = true) //开启表达式注解
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//Spring Security配置类
}
代码实现
基于方法级别权限控制,有三种方式
代码语言:javascript代码运行次数:0运行复制/**
* 查询所有产品
* @param page
* @param size
* @return
*/
// @RolesAllowed({"ADMI","USER"}) // JSR-250注解
// @RolesAllowed("ADMI") // JSR-250注解
// @Secured("ROLE_ADMI") // Secured注解
// @PreAuthorize("authentication.principal.username == 'jack'")//只有jack才可以访问
@RequestMapping("findAll")
public String findAll( Model model,
@RequestParam(value = "page",defaultValue = "1") Integer page,
@RequestParam(value = "size",defaultValue = "5") Integer size){
PageHelper.startPage(page,size);
List<Product> productList = this.productService.findAll();
PageInfo pageInfo = new PageInfo(productList);
model.addAttribute("pageInfo", pageInfo);
return "product-list";
}
代码语言:javascript代码运行次数:0运行复制uestMapping(“findAll”)
public String findAll( Model model,
@RequestParam(value = “page”,defaultValue = “1”) Integer page,
@RequestParam(value = “size”,defaultValue = “5”) Integer size){PageHelper.startPage(page,size);
List<Product> productList = this.productService.findAll();
PageInfo pageInfo = new PageInfo(productList);
model.addAttribute("pageInfo", pageInfo);
return "product-list";
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:202-10-14,如有侵权请联系 cloudcommunity@tencent 删除系统注解登录配置权限 #感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 10 条评论) |
本站网友 瑞兰玻尿酸注射除皱 | 12分钟前 发表 |
主题一般式指用户 | |
本站网友 中博教育 | 27分钟前 发表 |
userInfo.getStatus() == 0 ? false | |
本站网友 婆媳过招70回 | 26分钟前 发表 |
roles){ println("对应角 | |
本站网友 凤凰山主题公园 | 9分钟前 发表 |
(简单来说:系统判断用户是否有权限去做某些事情)这些概念是通用的 | |
本站网友 世界上最有效的减肥方法 | 10分钟前 发表 |
permissioname VARCHAR(50) | |
本站网友 年抛隐形眼镜 | 14分钟前 发表 |
"/img/**" | |
本站网友 南昌兼职会计 | 14分钟前 发表 |
FOREIG KEY (userId) REFERECES users(id) | |
本站网友 chouti | 6分钟前 发表 |
就要 | |
本站网友 百度工具栏下载 | 26分钟前 发表 |
这是一个流行的开源单点登录系统) Transparent authentication contextpropagation for Remote Method Invocation and HttpInvoker (一个Spring远程调用协议)用户登录认证表结构分析与创建代码语言:javascript代码运行次数:0运行复制-- 用户表 CREATE TABLE users( id VARCHAR(2) PRIMARY KEY |