Spring Security进阶

1.连接数据库进行数据的验证

Spring Security进行身份验证或者权限控制时,用户名和密码应该要和数据库的进行比较才行,用户的各种信息我们从数据库中去获取,不用自己在代码或者配置文件中写。

案例

1)创建项目

自己创建一个Maven项目

2)导入依赖

<parent>
<!--Spring boot-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-parent</artifactId>
<version>2.0.6.RELEASE</version>
</parent> <dependencies>
<!--Spring boot Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!--Spring Security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> <!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency> <!--数据库连接框架JPA-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>

3)创建启动类

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

4)配置文件

在项目的resources文件的目录下创建一个配置文件:application.properties

#连接数据库
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/你的数据库?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=用户名
spring.datasource.password=密码
#数据库表的生成
spring.jpa.generate-ddl=true
#显示执行的sql语句
spring.jpa.show-sql=true
#使用的数据库
spring.jpa.database=mysql

5)创建类

来创建一个实体层类、dao层接口、service层、控制层

实体类

//这个注解表示这个是实体类,对应数据库中的表,默认实体名就是类名
@Entity
public class UserInfo { //这个属性的表中的主键
@Id
//主键的生成策略,IDENTITY 主键自增长
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//用户名
private String username;
//密码
private String password;
//角色
private String roles; public Long getId() {
return id;
} public void setId(Long 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;
}
}

dao层接口

/*
* 继承JpaRepository<UserInfo,Long>接口,泛型一个是实体类,一个是主键类型
* */
public interface UserInfoDao extends JpaRepository<UserInfo,Long> {
//根据用户名查找用户
//(温馨提示:想要查找的话方法名要为 findBy属性字段 删除的话 deleteBy属性字段 ...以此类推这样才不报错)
UserInfo findByUsername(String username);
}

service层

public interface UserInfoService {
//根据用户名查找用户
UserInfo findByUsername(String username);
}
@Service
public class UserInfoServiceImpl implements UserInfoService { @Autowired
private UserInfoDao userInfoDao; //根据用户名返回用户
@Override
public UserInfo findByUsername(String username) {
UserInfo user = userInfoDao.findByUsername(username);
return user;
}
}

controller层

@RestController
@RequestMapping("/userInfo")
public class UserInfoController { @RequestMapping("common")
//方法执行前验证用户是否有该角色
@PreAuthorize(value = "hasAnyRole('normal','admin')")
public String commonUserInfo() {
return "==测试数据库 有两个角色==";
} @RequestMapping("admin")
//方法执行前验证是否有该角色
@PreAuthorize(value = "hasAnyRole('admin')")
public String adminUserInfo() {
return "==测试数据库 有一个角色==";
}
}

这些准备工作都做完之后,我们可以往数据库中插入一些数据,创建一个类,用来往数据库中添加数据的。

@Component
public class InitJdbc { @Autowired
private UserInfoDao userInfoDao; //Java自带的注解,程序启动的时候执行该方法,每启动一次执行一次,
//插入成功了,再启动项目的时候不想再重复插入,可以把@PostConstruct注释掉
@PostConstruct
public void init() {
//密码要加密
PasswordEncoder pe = new BCryptPasswordEncoder(); //添加一个用户
UserInfo userInfo = new UserInfo();
userInfo.setUsername("wangwu");
userInfo.setPassword(pe.encode("123456"));
userInfo.setRoles("normal");
userInfoDao.save(userInfo); //添加一个用户
UserInfo userInfo1 = new UserInfo();
userInfo1.setUsername("admin");
userInfo1.setPassword(pe.encode("admin"));
userInfo1.setRoles("admin");
userInfoDao.save(userInfo1); }
}

现在就可以启动项目看看数据库中是否插入成功数据了。

接下来做权限的验证==========

来写一个类,实现UserDetailService并实现它的方法

//把类交给spring容器管理
@Component
public class SecurityDetail implements UserDetailsService { @Autowired
private UserInfoDao userInfoDao; @Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { UserInfo userInfo = null; //UserDetails接口的实现类
User user = null;
//判断用户名不为空
if (s != null) {
//根据用户名查找用户
userInfo = userInfoDao.findByUsername(s);
//判断用户不为空
if (userInfo != null) {
//User类的第三个参数是集合,所有创建一个集合,获取用户的角色
List<GrantedAuthority> list = new ArrayList<>();
//获取用户的角色,获取到的角色开头一定要以"ROLE_"开头
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + userInfo.getRoles());
list.add(authority);
//User的构造器要返回三个参数:用户名、密码、集合的角色
user = new User(userInfo.getUsername(), userInfo.getPassword(), list);
}
} return user;
}
}

再写一个配置类,解析密码的加密方式

@Configuration
@EnableWebSecurity
//开启方法级别的验证
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired
private SecurityDetail securityDetail; @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//密码加密的方式
auth.userDetailsService(securityDetail).passwordEncoder(new BCryptPasswordEncoder()); }
}

现在可以进行测试了,启动项目,访问控制层的方法,只有方法上标记的角色才能访问该方法

2.认证和授权

authentication:认证,认证访问的用户是不是有效的用户,他是谁。

authorization:授权,访问的用户在系统中能干什么

RBAC:基于角色的访问控制(Role-Based Access Control),用户属于某个角色,而角色拥有某些权限。

权限:能对资源进行操作,比如增删改查

角色:自定义的,表示权限的聚合,一个角色可以有多个权限。

举例说明

设计角色:经理具有数据的修改、删除、查看等;员工只能查看数据。

一个公司中如果想把一个用户设置为经理,只需把他设置为经理这个角色,他就能有修改、删除、查看等操作了,如果公司新来普通员工,只需把他加入到员工这个角色里面就好了。这样,想让什么用户用户什么权限,只需把他加入到相应的角色里就OK了。

UserDetailService:这是一个接口,里面只有一个方法UserDetails loadUserByUsername(String var1),是根据用户名来获取数据库中信息的

主要的实现有:

InMemoryUserDetailsManager在内存中维护用户信息的,使用很方便,可是数据不是持久的

JdbcUserDetailsManager对数据库信息进行操作的,底层是基于jdbcTemplate的,可以使用这个类的方法来操作数据库数据。

UserDetails:提供用户信息的核心接口

// 权限的集合
Collection<? extends GrantedAuthority> getAuthorities();
//获取密码
String getPassword();
//获取用户名
String getUsername();
//用户是否存在
boolean isAccountNonExpired();
//用户是否锁定
boolean isAccountNonLocked();
//证书是否过期
boolean isCredentialsNonExpired();
//账户是否启用
boolean isEnabled();

UserDetails有一个实现类User

//他有两个构造器,参数和UserDetails的字段属性一样
public User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
this(username, password, true, true, true, true, authorities);
} public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
if (username != null && !"".equals(username) && password != null) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
} else {
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
}
}

2.1设置表

基于RBAC设置三张表,用户表,角色表,用户和角色的关联表 密码明文分别是 123 456 admin



-- 角色表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`id` int(11) NOT NULL,
`rolename` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色名称',
`rolememo` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色描述',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, 'USER', '普通用户');
INSERT INTO `sys_role` VALUES (2, 'READ', '只读');
INSERT INTO `sys_role` VALUES (3, 'ADMIN', '管理员'); SET FOREIGN_KEY_CHECKS = 1; -- 用户表 SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`realname` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '真实名字',
`isenable` int(11) NULL DEFAULT NULL COMMENT '是否开启认证',
`islock` int(11) NULL DEFAULT NULL COMMENT '是否锁定',
`isexpire` int(11) NULL DEFAULT NULL,
`incredentials` int(255) NULL DEFAULT NULL COMMENT '是否过期',
`createtime` date NULL DEFAULT NULL,
`logintime` date NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of sys_user 密码明文分别是 123 456 admin
-- ----------------------------
INSERT INTO `sys_user` VALUES (6, 'zs', '$2a$10$EGMo2XSdh49cDgXa0OzXYu36HfNssUf7zUDaNIz83AgWveA3GORYq', '张三', 1, 1, 1, 1, '2021-09-02', '2021-09-02');
INSERT INTO `sys_user` VALUES (7, 'lisi', '$2a$10$r9iLBYZzIIt/gyOngvPnZOBZaP4EW58etU1tLPoEh7hlYpydIaM6u', '李四', 1, 1, 1, 1, '2021-09-02', '2021-09-02');
INSERT INTO `sys_user` VALUES (8, 'admin', '$2a$10$P.I3zf7bEAmLmlSwaDOdMOdrxEyTT1QvbqfKC5YGQ7zHk5zUR/dCG', '管理员', 1, 1, 1, 1, '2021-09-02', '2021-09-02'); SET FOREIGN_KEY_CHECKS = 1; --关联表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`userid` int(11) NOT NULL,
`roleid` int(11) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES (6, 1);
INSERT INTO `sys_user_role` VALUES (7, 2);
INSERT INTO `sys_user_role` VALUES (8, 1);
INSERT INTO `sys_user_role` VALUES (8, 3); SET FOREIGN_KEY_CHECKS = 1;

2.2创建项目

2.3 导入依赖

把上一个项目的依赖导入进来,再加多一个spring整合mybatis的包

 <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>

2.4创建相关类

2.4.1实体类

创建User和Role的实体类,要继承UserDetails

public class SysUser implements UserDetails {

    private Integer id;
private String username;
private String password;
private String realName;
private boolean isEnable;
private boolean isExpired;
private boolean isLock;
private boolean isCredentials; private List<GrantedAuthority> grantedAuthorities; private Date createTime;
private Date loginTime; public SysUser() {
} public SysUser(String username, String password, String realName,
boolean isEnable, boolean isExpired, boolean isLock,
boolean isCredentials, List<GrantedAuthority> grantedAuthorities,
Date createTime, Date loginTime) {
this.username = username;
this.password = password;
this.realName = realName;
this.isEnable = isEnable;
this.isExpired = isExpired;
this.isLock = isLock;
this.isCredentials = isCredentials;
this.grantedAuthorities = grantedAuthorities;
this.createTime = createTime;
this.loginTime = loginTime;
} //角色的集合
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return grantedAuthorities;
} //密码
@Override
public String getPassword() {
return password;
} //用户名
@Override
public String getUsername() {
return username;
} //账号是否存在
@Override
public boolean isAccountNonExpired() {
return isExpired;
} //账号是否锁定
@Override
public boolean isAccountNonLocked() {
return isLock;
} //是否过期
@Override
public boolean isCredentialsNonExpired() {
return isCredentials;
} //是否启用
@Override
public boolean isEnabled() {
return isEnable;
} public void setId(Integer id) {
this.id = id;
} public void setUsername(String username) {
this.username = username;
} public void setPassword(String password) {
this.password = password;
} public void setRealName(String realName) {
this.realName = realName;
} public void setEnable(boolean enable) {
isEnable = enable;
} public void setExpired(boolean expired) {
isExpired = expired;
} public void setLock(boolean lock) {
isLock = lock;
} public void setCredentials(boolean credentials) {
isCredentials = credentials;
} public void setGrantedAuthorities(List<GrantedAuthority> grantedAuthorities) {
this.grantedAuthorities = grantedAuthorities;
} public void setCreateTime(Date createTime) {
this.createTime = createTime;
} public void setLoginTime(Date loginTime) {
this.loginTime = loginTime;
} public Integer getId() {
return id;
} public String getRealName() {
return realName;
} public Date getCreateTime() {
return createTime;
} public Date getLoginTime() {
return loginTime;
} @Override
public String toString() {
return "SysUser{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", realName='" + realName + '\'' +
", isEnable=" + isEnable +
", isExpired=" + isExpired +
", isLock=" + isLock +
", isCredentials=" + isCredentials +
", grantedAuthorities=" + grantedAuthorities +
", createTime=" + createTime +
", loginTime=" + loginTime +
'}';
}
}
public class SysRole {

    private Integer id;
private String role;
private String rolememo; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getRole() {
return role;
} public void setRole(String role) {
this.role = role;
} public String getRolememo() {
return rolememo;
} public void setRolememo(String rolememo) {
this.rolememo = rolememo;
} @Override
public String toString() {
return "SysRole{" +
"id=" + id +
", role='" + role + '\'' +
", rolememo='" + rolememo + '\'' +
'}';
}
}
2.4.2dao层和对应的xml文件
@Repository
public interface SysRoleMapper { //根据用户id查看角色
List<SysRole> selectByUserId(Integer userId);
} @Repository
public interface SysUserMapper { //插入用户
int insertSysUser(SysUser sysUser); //根据用户名查询用户
SysUser selectByUsername(String username);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.huang.security.mapper.SysRoleMapper"> <resultMap id="roleMapper" type="com.huang.security.entity.SysRole">
<id column="id" property="id"/>
<result column="rolename" property="role"/>
<result column="rolememo" property="rolememo"/>
</resultMap> <select id="selectByUserId" resultMap="roleMapper" >
SELECT sr.id,sr.rolename,sr.rolememo FROM sys_role AS sr
INNER JOIN sys_user_role AS sur ON sr.id = sur.roleid
WHERE sur.userid = #{userid}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.huang.security.mapper.SysUserMapper"> <resultMap id="userMapper" type="com.huang.security.entity.SysUser">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="realname" property="realName"/>
<result column="isenable" property="isEnable"/>
<result column="islock" property="isLock"/>
<result column="isexpire" property="isExpired"/>
<result column="incredentials" property="isCredentials"/>
<result column="createtime" property="createTime"/>
<result column="logintime" property="loginTime"/> </resultMap> <insert id="insertSysUser" parameterType="com.huang.security.entity.SysUser">
insert into sys_user(username,password,realname,isenable,islock,incredentials,createtime,logintime)
values(#{username},#{password},#{realName},#{isEnable},#{isLock},#{isCredentials},
#{createTime},#{loginTime})
</insert> <select id="selectByUsername" resultMap="userMapper" >
select id,username,password,realname,isenable,islock,isexpire,incredentials,createtime,logintime
from sys_user where username = #{username}
</select>
</mapper>
2.5service层

service层要实现UserDetailService接口,去获取数据库中的信息做返回

@Service
public class UserWnoRoleService implements UserDetailsService { @Autowired
private SysUserMapper userMapper; @Autowired
private SysRoleMapper roleMapper; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据用户名获取用户
SysUser user = userMapper.selectByUsername(username); System.out.println("==== Service =====");
String roleName = "";
List<GrantedAuthority> list = new ArrayList<>(); System.out.println("User" + user);
if (!StringUtils.isEmpty(user)) {
//根据用户id获取对应角色
List<SysRole> roles = roleMapper.selectByUserId(user.getId()); for (SysRole role : roles) {
//一个用户可能有多个角色,用集合保存,放到用户的集合里
roleName = role.getRole();
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + roleName);
list.add(authority);
user.setGrantedAuthorities(list);
} //返回的这个user是包含角色的
return user;
}
//可以返回自定义user,是因为实体类实现了UserDetails这个接口
return user;
}
}
2.6配置文件
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/库名?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=用户名
spring.datasource.password=密码 mybatis.mapper-locations=classpath:/mapper/*Mapper.xml
# 包起别名
mybatis.type-aliases-package=com.huang.security.entity
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2.7相关的配置类
@Configuration
//@EnableWebSecurity //如果是导入的jar包是spring-boot-starter-security可以不用写
public class MySecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("====== MySecurityConfig configure=============="); //匹配"/index","/login.html","/login" 不用验证(permit 许可),和登录相关的要放行
http.authorizeRequests().antMatchers("/index","/login.html","/login").permitAll()
//匹配只有相关角色才能访问的路径
.antMatchers("/access/user/**").hasRole("USER")
.antMatchers("/access/read/**").hasRole("READ")
.antMatchers("/access/admin/**").hasRole("ADMIN")
//所有都需要验证
.anyRequest().authenticated()
//执行结束
.and()
//表单的方式登录
.formLogin()
//登录的自定义视图页面
.loginPage("/login.html")
//登录访问的地址,表单中action的值
.loginProcessingUrl("/login")
.and()
//跨域安全的设置,禁用
.csrf().disable();
} @Qualifier("userWnoRoleService")
@Autowired
private UserDetailsService userDetailsService; @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//super.configure(auth);
// userDetailsService使用的是service层的 UserWnoRoleService,它实现了 UserDetailsService
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
2.8html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> 身份验证 <br>
<a href="/access/user">zs</a> <br>
<a href="/access/read">lisi</a> <br>
<a href="/access/admin">admin</a> <br>
<a href="/logout">退出</a>
</body>
</html> <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>自定义登录页</p>
<form action="/login" method="post">
用户名:<input type="text" name="username" value=""><br/>
密&nbsp;&nbsp;&nbsp;码:<input type="password" name="password" value=""><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
2.9controller层测试
@Controller
public class InitController { @GetMapping("index")
public String toIndex() {
return "forward:/index.html";
}
}
@RestController
@RequestMapping("/access")
public class UserWnoRoleController { @GetMapping("user")
public String sayUser() {
return "zs 是 user 角色";
} @GetMapping("read")
public String sayRead() {
return "lisi 是 read 角色";
} @GetMapping("admin")
public String sayAdmin() {
return "admin 是 user admin 角色";
}
}

个人笔记

Spring Security进阶的更多相关文章

  1. spring security进阶 使用数据库中的账户和密码认证

    目录 spring security 使用数据库中的账户和密码认证 一.原理分析 二.代码实现 1.新建一个javaWeb工程 2.用户认证的实现 3.测试 三.总结 spring security ...

  2. spring security进阶2 添加账户并对账户密码进行加密

    目录 spring security 添加账户并对账户密码进行加密 一.原理分析 1.1加密原理 1.2加密后的登录过程 二.代码实现 2.1添加用户的页面如下, register.html 2.2c ...

  3. spring security的BCryptPasswordEncoder加密和对密码验证的原理

    目录 BCryptPasswordEncoder加密和对密码验证的原理 一.加密算法和hash算法的区别 二.源码解析 1. encode方法 2. BCrypt.hashpw方法 3. matche ...

  4. Spring Security框架进阶、自定义登录

      1.Spring Security框架进阶 1.1 Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安 ...

  5. Spring Security实现OAuth2.0授权服务 - 进阶版

    <Spring Security实现OAuth2.0授权服务 - 基础版>介绍了如何使用Spring Security实现OAuth2.0授权和资源保护,但是使用的都是Spring Sec ...

  6. Spring Security OAuth2.0 - AuthorizationServer和ResourceServer分离

    <Spring Security实现OAuth2.0授权服务 - 基础版>和<Spring Security实现OAuth2.0授权服务 - 进阶版>两篇文章中介绍如何搭建OA ...

  7. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

  8. Spring Security OAuth2 开发指南

    官方原文:http://projects.spring.io/spring-security-oauth/docs/oauth2.html 翻译及修改补充:Alex Liao. 转载请注明来源:htt ...

  9. spring mvc 和spring security配置 web.xml设置

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmln ...

随机推荐

  1. Tom_No_01 IDEA tomcat 源码环境搭建

    1.下载源码 apache-tomcat-8.5.50-src 2.下载源码 放D盘,解压后根目录新建pom.xml和catalina-home pom.xml文件中内容为 <?xml vers ...

  2. js问题记录

    1.aixos请求响应302重定向时无法获取返回数据, 解决方法:在请求头中添加  headers: { 'X-Requested-With': 'XMLHttpRequest' },

  3. Linux下如何查看定位当前正在运行软件的配置文件

    netstat命令 用于显示与IP.TCP.UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况 netstat -lntup 说明: l:listening n:num t:tc ...

  4. springboot整合ehcache缓存失效

    最近做了个微信公众号后台,因为只是单应用就选用了ehcache来做本地缓存,主要是用于缓存微信的accece_token和jsapi_ticket.在使用ehcache的时候遇到了@Cacheable ...

  5. SQL语句(六)分页查询和联合查询

    目录 一.分页查询 语法格式 应用 二.联合查询 语法和作用 特点 应用 UNION和UNION ALL的区别 一.分页查询 语法格式 SELECT 查询列表 FROM 表 WHERE ... GRO ...

  6. swift文件调用oc分类时崩溃解决办法(可能全网唯一)

    背景 oc为基础创建的sdk混编工程,在被sdk关联的混编demo工程中swift文件调用时,会崩溃,提示找不到sdk中oc分类方法.常规的,在demo中设置-Objc和-all_load也还是会崩. ...

  7. Sci Adv | 上科大水雯箐/胡霁/钟桂生脑蛋白质组学研究揭示抑郁行为的新调控因子

    大脑是生物体内结构和功能最复杂的组织.近年来蓬勃发展的脑蛋白组学研究是绘制大脑功能分子图谱.全面理解大脑生理病理机制的必经途径.跨膜蛋白家族在突触信号传递和神经可塑性调节中扮演重要角色,许多跨膜蛋白与 ...

  8. Nginx 解析漏洞

    目录 漏洞复现 漏洞成因 修复方案 参考链接 该漏洞与Nginx.php版本无关,属于用户配置不当造成的解析漏洞. 漏洞复现 访问http://172.17.0.1/uploadfiles/nginx ...

  9. UNIX环境高级编程APUE练习3.2-不用fcntl实现dup2的功能

    1 题面 编写与dup2功能相同的函数,要求不调用fcntl函数,并且要有正确的出错处理. 2 基本思路 不能用fcntl,能够返回一个文件描述符的只有open和dup.而open会创建一个新的文件表 ...

  10. Block循环引用详解

    前言 在项目中经常用到block,使用不当就很容易因为循环引用而造成内存泄漏.本文分析了block循环引用形成原因以及处理办法,如果有什么不对或者疑问请留言. 什么情况下block会造成循环引用 bl ...