Commit 8b6b7c75 authored by WeiWei's avatar WeiWei

重写权限认证

parent 1a577745
......@@ -32,23 +32,14 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
......
package cn.quantgroup.cashloanflowboss;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableRedisHttpSession
@EnableTransactionManagement
@EnableAutoConfiguration
@SpringBootApplication(scanBasePackages = {"cn.quantgroup.cashloanflowboss"})
public class Bootstrap {
......
......@@ -2,6 +2,8 @@ package cn.quantgroup.cashloanflowboss.api.log.controller;
import cn.quantgroup.cashloanflowboss.api.log.model.LoginFormModel;
import cn.quantgroup.cashloanflowboss.api.log.service.LogService;
import cn.quantgroup.cashloanflowboss.component.security.Power;
import cn.quantgroup.cashloanflowboss.component.security.annotiation.Security;
import cn.quantgroup.cashloanflowboss.core.base.Result;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -37,6 +39,7 @@ public class LogController {
*
* @return
*/
@Security(authorityId = "Log.logout", power = Power.CREATE)
@DeleteMapping("/logout")
public Result<Boolean> logout() {
return new Result<>(ApplicationStatus.SUCCESS, this.logService.logout());
......
package cn.quantgroup.cashloanflowboss.api.log.model;
import cn.quantgroup.cashloanflowboss.validator.constraints.NotEmpty;
import cn.quantgroup.cashloanflowboss.component.validator.constraints.NotEmpty;
import lombok.Data;
/**
......
package cn.quantgroup.cashloanflowboss.api.log.model;
/**
* Created by WeiWei on 2019/7/26.
*/
public class Permission {
}
package cn.quantgroup.cashloanflowboss.api.log.model;
/**
* Created by WeiWei on 2019/7/26.
*/
public class UserInformation {
private String username;
private Permission authority;
}
package cn.quantgroup.cashloanflowboss.api.log.service;
import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserStatus;
import cn.quantgroup.cashloanflowboss.api.user.entity.User;
import cn.quantgroup.cashloanflowboss.api.user.service.UserService;
import cn.quantgroup.cashloanflowboss.component.security.Power;
import cn.quantgroup.cashloanflowboss.core.asserts.Assert;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationDictionary;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
import cn.quantgroup.cashloanflowboss.utils.JSONTools;
import cn.quantgroup.cashloanflowboss.utils.MD5Tools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.HashMap;
/**
* Created by WeiWei on 2019/7/22.
......@@ -22,7 +25,7 @@ import java.util.Objects;
public class LogService {
@Autowired
private AuthenticationManager authenticationManager;
private UserService userService;
@Autowired
private HttpServletRequest request;
......@@ -36,13 +39,23 @@ public class LogService {
*/
public boolean login(String username, String password) {
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(this.authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)));
User user = this.userService.getUser(username);
// 检查用户是否有效
Assert.isNull(user, ApplicationStatus.INVALID_USER);
// 检查用户是否被禁用
Assert.isTrue(UserStatus.DISABLED.equals(user.getStatus()), ApplicationStatus.DISABLED_USER);
// 检查密码是否正确
Assert.isFalse(user.getPassword().equalsIgnoreCase(MD5Tools.md5(password)), ApplicationStatus.USERNAME_OR_PASSWORD_ERROR);
HttpSession session = this.request.getSession(true);
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
session.setAttribute(ApplicationDictionary.SECURITY_KEY, JSONTools.serialize(new HashMap<String, Power>() {{
put("Log.logout", Power.CREATE);
}}));
return securityContext.getAuthentication().isAuthenticated();
return true;
}
......@@ -53,9 +66,9 @@ public class LogService {
*/
public boolean logout() {
new SecurityContextLogoutHandler().logout(this.request, null, SecurityContextHolder.getContext().getAuthentication());
this.request.getSession().removeAttribute(ApplicationDictionary.SECURITY_KEY);
return Objects.isNull(SecurityContextHolder.getContext().getAuthentication());
return true;
}
......
......@@ -4,7 +4,9 @@ import cn.quantgroup.cashloanflowboss.api.user.entity.User;
import cn.quantgroup.cashloanflowboss.api.user.model.Pagination;
import cn.quantgroup.cashloanflowboss.api.user.model.RegisterUserFormModel;
import cn.quantgroup.cashloanflowboss.api.user.service.UserService;
import cn.quantgroup.cashloanflowboss.validator.constraints.NotEmpty;
import cn.quantgroup.cashloanflowboss.component.security.Power;
import cn.quantgroup.cashloanflowboss.component.security.annotiation.Security;
import cn.quantgroup.cashloanflowboss.component.validator.constraints.NotEmpty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;
......
package cn.quantgroup.cashloanflowboss.api.user.model;
import cn.quantgroup.cashloanflowboss.validator.constraints.NotEmpty;
import cn.quantgroup.cashloanflowboss.component.validator.constraints.NotEmpty;
import lombok.Data;
/**
......
package cn.quantgroup.cashloanflowboss.component.security;
/**
* Created by WeiWei on 2019/7/26.
*/
public enum Power {
/**
* 新建
*/
CREATE,
/**
* 更新
*/
UPDATE,
/**
* 删除
*/
DELETE
}
package cn.quantgroup.cashloanflowboss.component.security;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
/**
* Created by WeiWei on 2018/2/1.
*/
public class SecurityAdvisor extends DefaultPointcutAdvisor {
public SecurityAdvisor(Pointcut pointcut, Advice advice) {
super(pointcut, advice);
}
}
package cn.quantgroup.cashloanflowboss.component.security;
import cn.quantgroup.cashloanflowboss.component.security.annotiation.Security;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
/**
* Created by WeiWei on 2018/2/1.
*/
@Configuration
public class SecurityConfiguration {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public SecurityPointcut<Security> securityPointcut() {
return new SecurityPointcut<>(Security.class);
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public SecurityInterceptor securityInterceptor() {
return new SecurityInterceptor();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public SecurityAdvisor securityAdvisor() {
return new SecurityAdvisor(securityPointcut(), securityInterceptor());
}
}
package cn.quantgroup.cashloanflowboss.component.security;
import cn.quantgroup.cashloanflowboss.component.security.annotiation.EnableSecurity;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.AdviceModeImportSelector;
import org.springframework.context.annotation.AutoProxyRegistrar;
import java.util.ArrayList;
import java.util.List;
/**
* Created by WeiWei on 2018/2/1.
*/
public class SecurityConfigurationSelector extends AdviceModeImportSelector<EnableSecurity> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return getProxyImports();
case ASPECTJ:
return getAspectJImports();
default:
return null;
}
}
/**
* 动态代理
*
* @return
*/
private String[] getProxyImports() {
List<String> result = new ArrayList<>();
result.add(AutoProxyRegistrar.class.getName());
result.add(SecurityConfiguration.class.getName());
return result.toArray(new String[result.size()]);
}
/**
* AspectJ代理
*
* @return
*/
private String[] getAspectJImports() {
// TODO 尚未支持
return null;
}
}
package cn.quantgroup.cashloanflowboss.component.security;
import org.aopalliance.intercept.MethodInvocation;
/**
* 安全处理拦截器
* <p>
* Created by WeiWei on 2018/12/24.
*/
public interface SecurityHandler {
boolean doAuthentication(final MethodInvocation invocation, String authorityId, Power[] power) throws Throwable;
}
\ No newline at end of file
package cn.quantgroup.cashloanflowboss.component.security;
import cn.quantgroup.cashloanflowboss.component.security.annotiation.Security;
import cn.quantgroup.cashloanflowboss.core.exception.ApplicationException;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.context.support.ApplicationObjectSupport;
import java.io.Serializable;
/**
* Created by WeiWei on 2018/2/1.
*/
public class SecurityInterceptor extends ApplicationObjectSupport implements MethodInterceptor, Serializable {
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
Security security = invocation.getMethod().getAnnotation(Security.class);
if (!this.getApplicationContext().getBean(SecurityHandler.class).doAuthentication(invocation, security.authorityId(), security.power())) {
throw new ApplicationException("认证失败");
}
return invocation.proceed();
}
}
package cn.quantgroup.cashloanflowboss.component.security;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* Created by WeiWei on 2018/2/1.
*/
class SecurityPointcut<T extends Annotation> extends StaticMethodMatcherPointcut implements Serializable {
private Class<T> pointcutClass;
public SecurityPointcut(Class<T> pointcutClass) {
this.pointcutClass = pointcutClass;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.isAnnotationPresent(this.pointcutClass);
}
}
package cn.quantgroup.cashloanflowboss.component.security.annotiation;
import cn.quantgroup.cashloanflowboss.component.security.SecurityConfigurationSelector;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by WeiWei on 2018/2/1.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SecurityConfigurationSelector.class)
public @interface EnableSecurity {
/**
* 是否使用子类代理目标类
*
* @return
*/
boolean proxyTargetClass() default false;
/**
* 代理模式
*
* @return
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* 排序
*
* @return
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
package cn.quantgroup.cashloanflowboss.component.security.annotiation;
import cn.quantgroup.cashloanflowboss.component.security.Power;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 安全认证注解
* <p>
* Created by WeiWei on 2018/12/24.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Security {
/**
* 权限ID
*
* @return
*/
String authorityId();
/**
* 权限
*
* @return
*/
Power[] power() default {};
}
\ No newline at end of file
package cn.quantgroup.cashloanflowboss.validator;
package cn.quantgroup.cashloanflowboss.component.validator;
import java.text.SimpleDateFormat;
import java.util.Date;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.Constraint;
import javax.validation.Payload;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.Constraint;
import javax.validation.Payload;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.Constraint;
import javax.validation.Payload;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import cn.quantgroup.cashloanflowboss.validator.IDValidator;
import cn.quantgroup.cashloanflowboss.component.validator.IDValidator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.Constraint;
import javax.validation.Payload;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.Constraint;
import javax.validation.Payload;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.Constraint;
import javax.validation.Payload;
......
package cn.quantgroup.cashloanflowboss.validator.constraints;
package cn.quantgroup.cashloanflowboss.component.validator.constraints;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
......
package cn.quantgroup.cashloanflowboss.core.configuration;
import cn.quantgroup.cashloanflowboss.component.security.Power;
import cn.quantgroup.cashloanflowboss.component.security.SecurityHandler;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationDictionary;
import cn.quantgroup.cashloanflowboss.utils.JSONTools;
import com.fasterxml.jackson.core.type.TypeReference;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
/**
* Created by WeiWei on 2019/7/26.
*/
@Configuration
public class ApplicationSecurityConfiguration implements SecurityHandler {
@Autowired
private HttpServletRequest request;
@Override
public boolean doAuthentication(MethodInvocation invocation, String authorityId, Power[] power) throws Throwable {
HttpSession session = this.request.getSession();
Map<String, Power> permissions = JSONTools.deserialize(String.valueOf(session.getAttribute(ApplicationDictionary.SECURITY_KEY)), new TypeReference<Map<String, Power>>() {});
return Objects.nonNull(permissions) && permissions.containsKey(authorityId) && Arrays.asList(power).contains(permissions.get(authorityId));
}
}
package cn.quantgroup.cashloanflowboss.core.configuration.security;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by WeiWei on 2019/7/23.
*/
@Component
public class AuthenticationLinstener implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.getWriter().write("wocuole");
}
}
package cn.quantgroup.cashloanflowboss.core.configuration.security;
import cn.quantgroup.cashloanflowboss.api.user.dictionary.UserStatus;
import cn.quantgroup.cashloanflowboss.api.user.entity.User;
import cn.quantgroup.cashloanflowboss.api.user.service.UserService;
import cn.quantgroup.cashloanflowboss.core.asserts.Assert;
import cn.quantgroup.cashloanflowboss.core.dictionary.ApplicationStatus;
import cn.quantgroup.cashloanflowboss.utils.MD5Tools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.Collection;
/**
* Created by WeiWei on 2019/7/22.
*/
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserService userService;
@Override
public boolean supports(Class<?> clazz) {
return true;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
User user = this.userService.getUser(authentication.getName());
// 检查用户是否存在
Assert.isNull(user, ApplicationStatus.INVALID_USER);
// 检查用户是否被禁用
Assert.isTrue(UserStatus.DISABLED.equals(user.getStatus()), ApplicationStatus.DISABLED_USER);
// 检查用户密码是否一致
Assert.isFalse(user.getPassword().equalsIgnoreCase(MD5Tools.md5(authentication.getCredentials().toString())), ApplicationStatus.USERNAME_OR_PASSWORD_ERROR);
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
return new UsernamePasswordAuthenticationToken(user, authentication.getCredentials(), authorities);
}
}
package cn.quantgroup.cashloanflowboss.core.configuration.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
/**
* Created by WeiWei on 2019/7/22.
*/
@Configuration
@EnableWebSecurity
@EnableRedisHttpSession
@EnableRedisRepositories
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/**");
http.authorizeRequests().antMatchers("/login").permitAll();
http.authorizeRequests().anyRequest().authenticated();
}
}
package cn.quantgroup.cashloanflowboss.core.dictionary;
/**
* 应用系统全局数据字典
* <p>
* Created by WeiWei on 2019/7/30.
*/
public final class ApplicationDictionary {
// 权限Session Key
public static final String SECURITY_KEY = "PERMISSION";
}
......@@ -10,7 +10,7 @@ server.port = 51200
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
# \u6570\u636E\u5E93\u8FDE\u63A5URL
spring.datasource.url = jdbc:mysql://172.17.5.14:31763/cash_loan_flow_boss?useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT%2b8
spring.datasource.url = jdbc:mysql://172.17.5.9:31763/cash_loan_flow_boss?useUnicode=true&characterEncoding=UTF8&serverTimezone=GMT%2b8
# \u6570\u636E\u5E93\u8D26\u53F7
spring.datasource.username = qa
......@@ -33,7 +33,7 @@ spring.datasource.hikari.connectionTestQuery = select 1
spring.redis.database = 8
# Redis\u670D\u52A1\u5668\u5730\u5740
spring.redis.host = 172.17.5.10
spring.redis.host = 172.17.5.16
# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3
spring.redis.port = 32244
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment