SpringSecurity
1 springsecurity 依赖包
<!-- security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- securitythymeleaf-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
2 springsecurity config 配置
实现UserDetailsService
@Service
public class UserServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据username 查询数据库
if (!"admin".equals(username)){
throw new UsernameNotFoundException("用户名或密码错误");
}
//根据查询的对象比较密码
String password = passwordEncoder.encode("123456");
//返回用户对象
return new User("admin",password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal,ROLE_abc,/toMain,/main.html,/insert,/select"));
}
}
创建WebSecurityConfig 继承 WebSecurityConfigurerAdapter 配置信息
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
实现configure(HttpSecurity http)
protected void configure(HttpSecurity http) throws Exception {
//表单登录
http.formLogin()
//自定义登录页面
.loginPage("/showLogin")
//自定义登录逻辑
.loginProcessingUrl("/login")
//登录成功跳转页面 必须是POST请求
.successForwardUrl("/toMain")
//自定义成功跳转页面
// .successHandler(new MyAuthenticationSuccessHandler("/toMain"))
//登录失败
.failureForwardUrl("/toError")
//自定义失败跳转页面
// .failureHandler(new MyAuthenticationFailureHandler("http://www.qq.com"))
//自定义用户名密码
// .usernameParameter("username")
// .passwordParameter("password")
;
//授权
http.authorizeRequests()
//放行页面 ant表达式 regex表达式
.antMatchers("/showLogin","/error.html","/**/*.jpg").permitAll()
//通过用户权限
// .antMatchers("/main1.html").hasAnyAuthority("admin")
//根据角色匹配,不能以ROLE_开头 严格区分大小写
// .antMatchers("/main1.html").hasAnyRole("abc")
// .antMatchers("/main1.html").hasIpAddress("基于IP地址控制")
// .regexMatchers()
//所有请求都必须认证登录
//注解@方式
.anyRequest().authenticated();
//自定义逻辑
// .anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");
//自定义403
http.exceptionHandling()
.accessDeniedHandler(myAccessDeniedHandler);
http.rememberMe()
//自定义参数
// .rememberMeParameter("")
//失效时间
// .tokenValiditySeconds()
//自定义记住我实现
// .rememberMeServices()
.userDetailsService(userService).tokenRepository(persistentTokenRepository);
//退出登录
http.logout()
.logoutUrl("/logout").logoutSuccessUrl("/login.html");
//csrf 跨域
//关闭csrf防护
// http.csrf().disable();
}
自动定义跳转页面
成功页
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private final String forwardUrl;
public MyAuthenticationSuccessHandler(String forwardUrl) {
this.forwardUrl = forwardUrl;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
// System.out.println(authentication.getAuthorities());
// System.out.println(authentication.getCredentials());
// System.out.println(authentication.getDetails());
// Object principal = authentication.getPrincipal();
WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) authentication.getDetails();
System.out.println(webAuthenticationDetails.getRemoteAddress());
httpServletResponse.sendRedirect(forwardUrl);
}
}
失败页
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
private final String forwardUrl;
public MyAuthenticationFailureHandler(String forwardUrl) {
this.forwardUrl = forwardUrl;
}
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.sendRedirect(forwardUrl);
}
}
403页
@Configuration
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter writer = httpServletResponse.getWriter();
writer.write("{\"status\":\"403\",\"msg\":\"权限不足,请联系管理员\"}");
writer.flush();
writer.close();
}
}
自定义控制访问逻辑
@Service
public class MyServiceImpl implements MyService{
@Override
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
String uri = request.getRequestURI();
Object principal = authentication.getPrincipal();
if (principal instanceof UserDetails){
UserDetails userDetails = (UserDetails) principal;
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
return authorities.contains(new SimpleGrantedAuthority(uri));
}
return false;
}
}
springsecurity oauth2
1 依赖包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zsecode</groupId>
<artifactId>springSecurityOauth</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springSecurityOauth</name>
<description>springSecurityOauth</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-redis</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.commons</groupId>-->
<!-- <artifactId>commons-pool2</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2 pojo
user
public class User implements UserDetails {
private String username;
private String password;
List<GrantedAuthority> authorities;
public User() {
}
public User(String username, String password, List<GrantedAuthority> authorities) {
this.username = username;
this.password = password;
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
UserService
@Service
public class UserService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new User("admin",passwordEncoder.encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
SecurityConfig
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/oauth/**","/login/**","/logout/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
AuthorizationServer
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserService userService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired
private TokenEnhancer tokenEnhancer;
// @Autowired
// private TokenStore tokenStore;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//token增强链
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> delegates = new ArrayList<>();
delegates.add(tokenEnhancer);
delegates.add(jwtAccessTokenConverter);
tokenEnhancerChain.setTokenEnhancers(delegates);
endpoints.userDetailsService(userService)
.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.accessTokenConverter(jwtAccessTokenConverter)
//token增强链
.tokenEnhancer(tokenEnhancerChain);
// .tokenStore(tokenStore);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
//clientID
.withClient("admin")
//client密码
.secret(passwordEncoder.encode("123456"))
//令牌失效时间
.accessTokenValiditySeconds(36000)
//重定向地址
.redirectUris("http://www.baidu.com")
//授权范围
.scopes("all")
//授权类型
.authorizedGrantTypes("authorization_code","password","refresh_token");
}
}
JwtTokenConfig
@Configuration
public class JwtTokenConfig {
@Bean
public TokenStore jwtTokenStore(){
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("xxxx");
return jwtAccessTokenConverter;
}
@Bean
public TokenEnhancer tokenEnhancer(){
return new MyTokenEnhancer();
}
}
MyTokenEnhancer
public class MyTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
Map<String,Object> map = new HashMap<>();
map.put("enhancer","enhancer info");
((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(map);
return oAuth2AccessToken;
}
}
RedisConfig
@Configuration
public class RedisConfig {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore(){
return new RedisTokenStore(redisConnectionFactory);
}
}
ResourceConfig
@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.requestMatchers().mvcMatchers("/user/**");
}
}