SpringBoot之——SpringBoot+SpringSecurityOAuth2.0 实现SSO单点登录(一)--服务端

SSO Server

前期准备:

使用maven构建项目,导入1.5.4SpringBootjar

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.4.RELEASE</version>

<relativePath/>

</parent>

导入所必须的springboot集成securityjarspring-boot-starter-security以及它的依赖包spring-security-jwt

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-security</artifactId>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-jwt</artifactId>

基于OAuth认证,导入

<groupId>org.springframework.security.oauth</groupId>

<artifactId>spring-security-oauth2</artifactId>

由于是web项目继续导入spring-boot-starter-web

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

页面显示模版使用springBoot官方推荐的thymeleaf导入spring-boot-starter-thymeleaf

使用Java工具包中的keytool制作证书serverKeystore.jks,设置别名为alias1,密码为123456

命令:keytool -genkey -alias alias1 -keyalg RSA -keysize 1024 -keystore serverKeystore.jks -validity 365

将证书放入resource文件夹

编码:

一:新建OAuthConfigurer.java继承AuthorizationServerConfigurerAdapter,实现该类所有方法,该类为OAuth认证配置类

1.配置客户端认证方式以及客户端连接参数设置:

public void configure(ClientDetailsServiceConfigurer clients)

            throws Exception {

        clients.inMemory()

//该配置为SSO客户端配置所需的

client-id: acme;client-secret: acmesecret

.withClient("acme").secret("acmesecret")

                 .authorizedGrantTypes("authorization_code","refresh_token").scopes("openid");

    }

2.配置oauth认证安全策略 从表单提交经过OAuth认证

    public void configure(AuthorizationServerSecurityConfigurersecurity)

            throws Exception {

        security.tokenKeyAccess("permitAll()").checkTokenAccess(

                "isAuthenticated()").allowFormAuthenticationForClients();

    }

3.认证转换器配置使用@Bean的方式注入到当前方法中

首先实现一个方法加上@Bean注解交给IOC容器管理这个Bean,在该方法中设置之前放置证书的路径以及设置的别名和密码,setJwt认证转换器中,并返回一个转换器

@Bean

public JwtAccessTokenConverter jwtAccessTokenConverter(){

JwtAccessTokenConverter converter = new JwtAccessTokenConverter();

KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource("serverKeystore.jks"),"123456".toCharArray()).getKeyPair("alias1");

converter.setKeyPair(keyPair);

return converter;

}

之后注入到认证转换器配置中调用

    public void configure(AuthorizationServerEndpointsConfigurerendpoints)

            throws Exception {

        endpoints.accessTokenConverter(jwtAccessTokenConverter());

}

最后在该类上加上@Configuration注解,表明这是一个beans上下文配置Spring容器,加上@EnableAuthorizationServer注解开启Auth认证服务器

二:新建类SecurityConfiguration继承WebSecurityConfigurerAdapter 配置认证管理器,以及安全策略

配置认证管理器(AuthenticationManagerBuilder):

两种方式:

1. 配置固定用户名密码

auth.inMemoryAuthentication()

            .withUser("user")  //用户名

               .password("user")//密码

                .roles("USER")//角色

2. 通过实现userDetailsService接口类重写loadUserByUsername()方法返回UserDetails进行密码匹配

auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());

auth.eraseCredentials(false);

该密码加密方式为Springsecurity推荐的加密方式,放弃之前的PasswordEncoder改用BCryptPasswordEncoder()

②配置安全策略(HttpSecurity)

http

//关闭csrf

//.csrf().disable()

//取消安全报文头 默认开启  可配置部分开启或全关

//.headers().disable()

//登录页面url 配置登录成功后调用的方法

.formLogin().loginPage("/login").permitAll().successHandler(loginSuccessHandler())

.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()

.authorizeRequests()

//配置这些链接无需验证

.antMatchers("/regist","/toregist").permitAll()

//除以上路径都需要验证

.anyRequest().authenticated()

//路径角色验证

//.antMatchers("/admin/**").hasRole("ADMIN")

//排除该路径角色认证  注意顺序自上而下

//.antMatchers("/**").hasRole("USER")

.and()

//注销登录  默认支持 销毁session并且清空配置的rememberMe()认证 跳转登录页 或配置的注销成功页面

.logout()

.deleteCookies("remove")

.invalidateHttpSession(false)

.logoutUrl("/logout")

.logoutSuccessUrl("/logoutsuccess")

.and()

//http参数中包含一个名为“remember-me”的参数,不管session是否过期,用户记录将会被记保存下来

.rememberMe()

//.and()

////http映射https

//.portMapper()

//.http(8080).mapsTo(9443)

.and()

//配置http认证

.httpBasic()

.and()

//当用户进行重复登录时  强制销毁前一个登录用户  配置此应用必须添加Listener  HttpSessionEventPublisher

.sessionManagement()

            .maximumSessions(1)

            .expiredUrl("/login?expired");


三:编写SecurityUser类继承当前User类并且实现UserDetails接口

在构造方法中塞入需要返回给客户端的权限信息

四:编写CustomUserDetailsService类实现UserDetailsService接口

实现loadUserByUsername()方法将传入的用户名进行数据查询,并返回经过SecurityUser包装的UserDetails对象

五:根据需要新建LoginSuccessHandler类继承SavedRequestAwareAuthenticationSuccessHandler

重写onAuthenticationSuccess()方法,通过安全策略配置登录成功后调用该类,用作记录登录时间等日志信息

猜你喜欢

转载自blog.csdn.net/l1028386804/article/details/81023044