SpringSecurity服务器端配置说明

服务器端配置说明


🍎🍏💜👛🍇🍑🍐🍍🍌🍉🍈🍓⏰👮👮‍♀🥕🚑🚙🌈📷🎯📧🤡💙💑🗂🏝🌾🏤

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.授权服务器配置

代码结构图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rMxB4Q2e-1661221320909)(../AppData/Roaming/Typora/typora-user-images/)]

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()");
	}
}

JwtTokenEnhancer.java

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;
	}
}

JwtTokenStoreConfig.java

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();
	}
}

ResourceServerConfig.java

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/**");
	}
}

SecurityConfig.java

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文件夹下配置

LoginController.java

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";
    }
}

UserController.java

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文件夹下配置

UserDao.java

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文件夹下配置

SysPermission.java

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 +
                '}';
    }
}

SysRole.java

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;
    }
}

SysUser.java

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文件夹下配置

UserService.java

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
在这里插入图片描述

到服务器端的认证系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgAjHjf2-1661221320915)(../AppData/Roaming/Typora/typora-user-images/)]

授权认证成功后跳转到指定客户端的页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K0daaTSK-1661221320917)(../AppData/Roaming/Typora/typora-user-images/)]

点击登录(成功登录到8081客户端)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fdCVT7Ct-1661221320923)(../AppData/Roaming/Typora/typora-user-images/)]

此时登录另一个客户端8082,确认是否也已经授权,免登录了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CHaJ2ZlF-1661221320926)(../AppData/Roaming/Typora/typora-user-images/image-20220819155835356.png)]

成功登录到8082,点击登录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P4hJJmYE-1661221320934)(../AppData/Roaming/Typora/typora-user-images/)]

没问题了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aMycLcJs-1661221320935)(../AppData/Roaming/Typora/typora-user-images/image-20220819160017255.png)]

登录到8080自己服务器的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MkPBN3Vz-1661221320937)(../AppData/Roaming/Typora/typora-user-images/)]

成功登录自己服务器的首页(user:zhangsan)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N0qrfvov-1661221320942)(../AppData/Roaming/Typora/typora-user-images/)]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

篮球小童_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值