服务器端配置说明
文章目录
🍎🍏💜👛🍇🍑🍐🍍🍌🍉🍈🍓⏰👮👮♀🥕🚑🚙🌈📷🎯📧🤡💙💑🗂🏝🌾🏤
1.创建一个可以正常启动的SpringBoot工程
- github代码地址:springsecurityoauth2-Server-Makaixuan(分支)
🔗https://github.com/MaKaixuanGitHub/Spring-Security.git
- Login用户:
username:zhangsan
password:123456
username:lisi
password:123456
- 服务器端Tomcat server地址:
🔗http://localhost:8080
2.授权服务器配置
代码结构图:
2.1 config文件夹下配置
AuthorizationServerConfig.java
package com.xxxx.springsecurityoauth2demo.config;
/**
* 授权服务器配置
*
* @author makx
* @since 1.0.0
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserService userService;
@Autowired
@Qualifier("jwtTokenStore")
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private JwtTokenEnhancer jwtTokenEnhancer;
/**
* 使用密码模式所需配置
* 该方法是用来配置Authorization Server endpoints的一些非安全特性的,
* 比如token存储、token自定义、授权类型等等的
* 默认情况下,你不需要做任何事情,除非你需要密码授权,
* 那么在这种情况下你需要提供一个AuthenticationManager
* @param endpoints endpoints
* @throws Exception Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
//配置JWT内容增强器
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> delegates = new ArrayList<>();
delegates.add(jwtTokenEnhancer);
delegates.add(jwtAccessTokenConverter);
enhancerChain.setTokenEnhancers(delegates);
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userService)
//配置存储令牌策略
.tokenStore(tokenStore)
.accessTokenConverter(jwtAccessTokenConverter)
.tokenEnhancer(enhancerChain);
}
/***
* 配置ClientDetailsService
* 注意,除非你在下面的configure(AuthorizationServerEndpointsConfigurer)
* 中指定了一个AuthenticationManager,
* 否则密码授权方式不可用。
* 至少配置一个client,否则服务器将不会启动。
* @param clients clients
* @throws Exception Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory()
//配置client-id
.withClient("admin")
//配置client-secret
.secret(passwordEncoder.encode("112233"))
//配置访问token的有效期
.accessTokenValiditySeconds(10)
//配置刷新Token的有效期
.refreshTokenValiditySeconds(864000)
//配置redirect_uri,用于授权成功后跳转
.redirectUris("http://localhost:8081/login")
//自动授权配置
.autoApprove(true)
//配置申请的权限范围
.scopes("all")
//配置grant_type,表示授权类型
.authorizedGrantTypes("password","refresh_token",
"authorization_code")
.and()
.withClient("makaixuan")
.secret(passwordEncoder.encode("332211"))
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(864000)
.redirectUris("http://localhost:8082/login")
.autoApprove(true)
.scopes("all")
.authorizedGrantTypes("password","refresh_token",
"authorization_code");
}
/***
* 获取秘钥需要身份认证
* 配置授权服务器的安全,意味着实际上是/oauth/token端点。
* /oauth/authorize端点也应该是安全的
* 默认的设置覆盖到了绝大多数需求,所以一般情况下你不需要做任何事情。
* @param security security
* @throws Exception Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
//获取秘钥需要身份认证,使用单点登录时必须配置
security.tokenKeyAccess("isAuthenticated()");
}
}
package com.xxxx.springsecurityoauth2demo.config;
/**
* JWT内容增强器
*
* @author makx
* @since 1.0.0
*/
public class JwtTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
OAuth2Authentication authentication) {
Map<String,Object> info = new HashMap<>();
info.put("enhance","enhance info");
((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(info);
return accessToken;
}
}
package com.xxxx.springsecurityoauth2demo.config;
/**
* JwtToken配置类
*
* @author makx
* @since 1.0.0
*/
@Configuration
public class JwtTokenStoreConfig {
@Bean
public TokenStore jwtTokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
//配置JWT使用的秘钥
accessTokenConverter.setSigningKey("test_key");
return accessTokenConverter;
}
@Bean
public JwtTokenEnhancer jwtTokenEnhancer(){
return new JwtTokenEnhancer();
}
}
package com.xxxx.springsecurityoauth2demo.config;
/**
* 资源服务器配置
*
* @author makx
* @since 1.0.0
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.requestMatchers()
.antMatchers("/user/**");
}
}
package com.xxxx.springsecurityoauth2demo.config;
/**
* Security配置类
* @author makx
* @since 1.0.0
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("SecurityConfig========>configure start");
http.authorizeRequests()
.antMatchers("/oauth/**","/login/**", "logout/**").permitAll()
.anyRequest().authenticated() // 其他地址的访问均需验证权限
.and()
.formLogin()
.loginPage("/login")
.and()
.logout().logoutSuccessUrl("/");
http.csrf().disable();
System.out.println("SecurityConfig========>configure end");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
@Override
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
2.2 controller文件夹下配置
package com.xxxx.springsecurityoauth2demo.controller;
@Controller
public class LoginController {
@RequestMapping("/login")
public String login() {
System.out.println("LoginController====================>login");
return "login";
}
@GetMapping("/index")
public String index() {
return "index";
}
@RequestMapping("/mian")
public String main() {
System.out.println("LoginController====================>login");
return "redirect:main.html";
}
}
package com.xxxx.springsecurityoauth2demo.controller;
/**
* @author makx
* @since 1.0.0
*/
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 获取当前用户
* @param authentication
* @return
*/
@RequestMapping("/getCurrentUser")
public Object getCurrentUser(Authentication authentication,
HttpServletRequest request){
String head = request.getHeader("Authorization");
String token = head.substring(head.indexOf("bearer") + 7);
return Jwts.parser()
.setSigningKey("test_key".getBytes(StandardCharsets.UTF_8))
.parseClaimsJws(token)
.getBody();
}
}
2.3 dao文件夹下配置
package com.xxxx.springsecurityoauth2demo.dao;
@Repository
public class UserDao {
@Autowired
private PasswordEncoder passwordEncoder;
private SysRole admin = new SysRole("ADMIN", "管理员");
private SysRole developer = new SysRole("DEVELOPER", "开发者");
{
SysPermission p1 = new SysPermission();
p1.setCode("memberExport");
p1.setName("会员列表导出");
p1.setUrl("/member/export");
SysPermission p2 = new SysPermission();
p2.setCode("BookList");
p2.setName("图书列表");
p2.setUrl("/book/list");
admin.setPermissionList(Arrays.asList(p1, p2));
developer.setPermissionList(Arrays.asList(p1));
}
/**
* 用户登录验证
* @param username username
* @return username
*/
public SysUser selectByName(String username) {
System.out.println("从数据库中查询用户");
System.out.println("username=================> " + username);
if ("zhangsan".equals(username)) {
String password = passwordEncoder.encode("123456");
SysUser sysUser = new SysUser("zhangsan", password);
sysUser.setRoleList(Arrays.asList(admin, developer));
return sysUser;
} else if ("lisi".equals(username)) {
String password = passwordEncoder.encode("123456");
SysUser sysUser = new SysUser("lisi", password);
sysUser.setRoleList(Arrays.asList(developer));
return sysUser;
}
return null;
}
}
2.4pojo文件夹下配置
package com.xxxx.springsecurityoauth2demo.pojo;
public class SysPermission implements Serializable {
private Long id;
/**
* 权限名称
*/
private String name;
/**
* 权限字符串
*/
private String code;
/**
* 资源类型
*/
private Integer type;
/**
* URL
*/
private String url;
/**
* 排序
*/
private Integer sort;
/**
* 父菜单ID
*/
private Long pid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getSort() {
return sort;
}
public void setSort(Integer sort) {
this.sort = sort;
}
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
@Override
public String toString() {
return "SysPermission{" +
"id=" + id +
", name='" + name + '\'' +
", code='" + code + '\'' +
", type=" + type +
", url='" + url + '\'' +
", sort=" + sort +
", pid=" + pid +
'}';
}
}
package com.xxxx.springsecurityoauth2demo.pojo;
public class SysRole implements Serializable {
private Long id;
/**
* 角色编码
*/
private String roleCode;
/**
* 角色名称
*/
private String roleName;
/**
* 角色拥有的权限
*/
private List<SysPermission> permissionList;
public SysRole() {
}
public SysRole(String roleCode, String roleName) {
this.roleCode = roleCode;
this.roleName = roleName;
}
@Override
public String toString() {
return "SysRole{" +
"id=" + id +
", roleCode='" + roleCode + '\'' +
", roleName='" + roleName + '\'' +
", permissionList=" + permissionList +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRoleCode() {
return roleCode;
}
public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public List<SysPermission> getPermissionList() {
return permissionList;
}
public void setPermissionList(List<SysPermission> permissionList) {
this.permissionList = permissionList;
}
}
package com.xxxx.springsecurityoauth2demo.pojo;
public class SysUser implements Serializable {
private Long id;
/**
* 用户编号
*/
private String usercode;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 盐
*/
private String salt;
/**
* 用户角色
*/
private List<SysRole> roleList;
public SysUser(String username, String password) {
this.username = username;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsercode() {
return usercode;
}
public void setUsercode(String usercode) {
this.usercode = usercode;
}
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 getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public List<SysRole> getRoleList() {
return roleList;
}
public void setRoleList(List<SysRole> roleList) {
this.roleList = roleList;
}
@Override
public String toString() {
return "SysUser{" +
"id=" + id +
", usercode='" + usercode + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
", salt='" + salt + '\'' +
", roleList=" + roleList +
'}';
}
}
2.5 service文件夹下配置
package com.xxxx.springsecurityoauth2demo.service;
/**
* 自定义登录逻辑
* @author makx
* @since 1.0.0
*/
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
SysUser sysUser = userDao.selectByName(username);
if (null == sysUser) {
throw new UsernameNotFoundException(username);
}
List<GrantedAuthority> authorities = new ArrayList<>();
for (SysRole role : sysUser.getRoleList()) {
System.out.println("角色拥有权限role.getPermissionList()============> "
+ role.getPermissionList());
for (SysPermission permission : role.getPermissionList()) {
authorities.add(new SimpleGrantedAuthority(permission.getCode()));
}
}
System.out.println("UserService================>authorities: "+authorities);
return new User(sysUser.getUsername(), sysUser.getPassword(), authorities);
}
}
3.Login认证登录测试
从客户端来的请求:
🔗http://localhost:8081
到服务器端的认证系统
授权认证成功后跳转到指定客户端的页面
点击登录(成功登录到8081客户端)
此时登录另一个客户端8082,确认是否也已经授权,免登录了
成功登录到8082,点击登录
没问题了
登录到8080自己服务器的
成功登录自己服务器的首页(user:zhangsan)