java乾貨系列—權限框架spring security

廢話不說

第一步-數據庫建表


java乾貨系列—權限框架spring security

其中六張表“ums_role、ums_user、ums_permission、ums_user_permission_relation、ums_user_role_relation、ums_role_permission_relation”

第二步-打開idea

maven引入jar

<code>
<dependency>
<groupid>org.springframework.boot/<groupid>
<artifactid>spring-boot-starter-security/<artifactid>
/<dependency>/<code>

第三部創建SecurityConfig

<code>/**
* SpringSecurity的配置
* configure(HttpSecurity httpSecurity):用於配置需要攔截的URL路徑,jwt過濾器及出異常後的處理器;
* configure(AuthenticationManagerBuilder auth):用於配置UserDetailsS​​ervice及PasswordEncoder;
* RestfulAccessDeniedHandler:當用戶沒有訪問權限時的處理器,用於返回JSON格式的處理結果;
* RestAuthenticationEntryPoint:當未登錄或令牌失效時,返回JSON格式的結果;
* UserDetailsS​​ervice:SpringSecurity定義的核心接口,根據用戶名獲取用戶信息,需要自行實現;
* 用戶詳細信息:SpringSecurity定義為封裝的用戶信息的類(主要是用戶信息和權限),需要自行實現;
* PasswordEncoder:SpringSecurity定義的用於對密碼進行編碼及比對的接口,當前使用的是BCryptPasswordEncoder;
* JwtAuthenticationTokenFilter:在用戶名和密碼驗證前添加的過濾器,如果有jwt的令牌,會自行根據令牌信息進行登錄。

*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UmsUserService umsUserService;
@Autowired
private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf()// 由於使用的是JWT,我們這裡不需要csrf
.disable()
.sessionManagement()// 基於token,所以不需要session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, // 允許對於網站靜態資源的無授權訪問
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/swagger-resources/**",
"/v2/api-docs/**"
)
.permitAll()
.antMatchers("/user/login", "/user/register")// 對登錄註冊要允許匿名訪問
.permitAll()
.antMatchers(HttpMethod.OPTIONS)//跨域請求會先進行一次options請求
.permitAll()
//TODO 測試時全部運行訪問
.antMatchers("/**")
.permitAll()
.anyRequest()// 除上面外的所有請求全部需要鑑權認證
.authenticated();
// 禁用緩存

httpSecurity.headers().cacheControl();
// 添加JWT filter
httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
//添加自定義未授權和未登錄結果返回
httpSecurity.exceptionHandling()
.accessDeniedHandler(restfulAccessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint);
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService())
.passwordEncoder(passwordEncoder());
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public UserDetailsService userDetailsService() {
//獲取登錄用戶信息
return username -> {
UmsUser User = umsUserService.getUserByUsername(username);

/**
* 用戶狀態不為1的時候 為鎖定用戶狀態
* 常見異常 AuthenticationManager jar
* UsernameNotFoundException 用戶找不到
* BadCredentialsException 壞的憑據
* AccountStatusException 用戶狀態異常它包含如下子類
* AccountExpiredException 賬戶過期
* LockedException 賬戶鎖定
* DisabledException 賬戶不可用
* CredentialsExpiredException 證書過期
*/

if (null != User) {

//用戶狀態不為1的時候 為鎖定用戶狀態

if(1 == User.getStatus()) {
List<umspermission> permissionList = umsUserService.getPermissionList(User.getId());
return new AdminUserDetails(User, permissionList);
}
throw new LockedException("用戶被凍結");

}
throw new UsernameNotFoundException("用戶名或密碼錯誤");
};
}

@Bean
public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
return new JwtAuthenticationTokenFilter();
}

/**
* 允許跨域調用的過濾器
*/
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.setAllowCredentials(true);
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return new CorsFilter(source);
}

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}

}
/<umspermission>/<code>

其中umsUserService

<code>public interface UmsUserService {
/**
* 根據用戶名獲取後臺管理員

*/
UmsUser getUserByUsername(String username);

/**
* 註冊功能
*/
Boolean register(UmsUser umsAdminParam);

/**
* 登錄功能
* @param username 用戶名
* @param password 密碼
* @return 生成的JWT的token
*/
String login(String username, String password, HttpServletRequest request);

/**
* 獲取用戶所有權限(包括角色權限和+-權限)
*/
List<umspermission> getPermissionList(Long adminId);



}/<umspermission>/<code>

第四步創建AdminUserDetails

<code>/**
* SpringSecurity需要的用戶詳情
*/
public class AdminUserDetails implements UserDetails {
private UmsUser umsUser;
private List<umspermission> permissionList;
public AdminUserDetails(UmsUser umsUser,List<umspermission> permissionList) {
this.umsUser = umsUser;
this.permissionList = permissionList;
}

@Override
public Collection extends GrantedAuthority> getAuthorities() {
//返回當前用戶的權限
return permissionList.stream()
.filter(permission -> permission.getValue()!=null)
.map(permission ->new SimpleGrantedAuthority(permission.getValue()))
.collect(Collectors.toList());

}

@Override
public String getPassword() {
return umsUser.getPassword();
}

@Override
public String getUsername() {
return umsUser.getUsername();
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return umsUser.getStatus().equals(1);
}
}
/<umspermission>/<umspermission>/<code>

書寫userServiceimpl

<code>@Service
public class UmsUserServiceImpl implements UmsUserService {
private static final Logger LOGGER = LoggerFactory.getLogger(UmsUserServiceImpl.class);
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private PasswordEncoder passwordEncoder;
@Value("${jwt.tokenHead}")
private String tokenHead;
@Autowired
private UmsUserMapper umsUserMapper;
@Autowired

private UmsUserRoleRelationDao umsUserRoleRelationDao;
@Autowired
private UmsUserLoginLogMapper umsUserLoginLogMapper;

@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private ObjectMapper objectMapper;

@Override
public UmsUser getUserByUsername(String username) {

return umsUserMapper.selectByUsername(username);
}

@Override
public Boolean register(UmsUser umsAdminParam) {
umsAdminParam.setGmtCreate(DateUtil.getNowDate());
umsAdminParam.setStatus(1);

//TODO springSecurity 進行密碼加密 加密方式沒有shiro方便設置
String encodePassword = passwordEncoder.encode(umsAdminParam.getPassword());
umsAdminParam.setPassword(encodePassword);

Integer result = umsUserMapper.insertSelective(umsAdminParam);

return (result==1)?true:false;
}

@Override
public String login(String username, String password, HttpServletRequest request){

String token = null;
try {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadCredentialsException("密碼不正確");
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
token = jwtTokenUtil.generateToken(userDetails);
} catch (AuthenticationException e) {
LOGGER.warn("登錄異常:{}", e.getMessage());
}
return token;
}

@Override

public List<umspermission> getPermissionList(Long adminId) {
return umsUserRoleRelationDao.getPermissionList(adminId);
}/<umspermission>/<code>

最後為controller

<code>@Controller
@Api(tags = "UmsUserController", description = "後臺用戶管理")
@RequestMapping("/user")
public class UmsUserController {
@Autowired
private UmsUserService UserService;
@Value("${jwt.tokenHeader}")
private String tokenHeader;
@Value("${jwt.tokenHead}")
private String tokenHead;

//test role
@ApiOperation(value = "角色測試")
@RequestMapping(value = "/testRole", method = RequestMethod.GET)
@PreAuthorize("hasRole('root')")
@ResponseBody
public CommonResult<string> getRole() {
return CommonResult.success("角色可以訪問");
}

//test role
@ApiOperation(value = "多項角色測試")
@RequestMapping(value = "/testRoleAll", method = RequestMethod.GET)
@PreAuthorize("hasAnyRole('role','admin')")
@ResponseBody
public CommonResult<string> getAllRole() {
return CommonResult.success("角色可以訪問");
}

//test role
@ApiOperation(value = "權限測試")
@RequestMapping(value = "/testPermission", method = RequestMethod.GET)
@PreAuthorize("hasAuthority('remove')")
@ResponseBody
public CommonResult<string> getPermission() {
return CommonResult.success("權限可以訪問");
}
//test role
@ApiOperation(value = "多項權限測試")
@RequestMapping(value = "/testPermissionAll", method = RequestMethod.GET)

@PreAuthorize("hasAnyAuthority('add','remonve')")
@ResponseBody
public CommonResult<string> getAllPermission() {
return CommonResult.success("權限可以訪問");
}

@ApiOperation(value = "用戶註冊")
@RequestMapping(value = "/register", method = RequestMethod.POST)
@ResponseBody
public CommonResult<boolean> register(@RequestBody UmsUser umsUserParam, BindingResult result) {
Boolean umsUser = UserService.register(umsUserParam);
if (umsUser == false) {
CommonResult.failed();
}
return CommonResult.success(umsUser);
}

@ApiOperation(value = "登錄以後返回token")
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public CommonResult login(@RequestBody UmsUserLoginParam umsUserLoginParam, HttpServletRequest request,BindingResult result) {
String token = UserService.login(umsUserLoginParam.getUsername(), umsUserLoginParam.getPassword(),request);
if (null == token) {
return CommonResult.validateFailed("用戶名或密碼錯誤");
}else if("invalidInvalidInvalid".equals(token)){
return CommonResult.validateFailed("用戶被鎖定");
}
Map<string> tokenMap = new HashMap<>();
tokenMap.put("token", token);
tokenMap.put("tokenHead", tokenHead);
return CommonResult.success(tokenMap);
}

@ApiOperation("獲取用戶所有權限(包括+-權限)")
@RequestMapping(value = "/permission/{UserId}", method = RequestMethod.GET)
@ResponseBody
public CommonResult<list>> getPermissionList(@PathVariable Long UserId) {
List<umspermission> permissionList = UserService.getPermissionList(UserId);
return CommonResult.success(permissionList);
}

}/<umspermission>/<list>/<string>/<boolean>/<string>/<string>/<string>/<string>/<code>


分享到:


相關文章: