【无标题】
作者:互联网
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、Spring Security是什么?
Spring Security是一个专注于为Java应用提供限权控制的框架吗,有以下优点:
1.对身份认证和授权提供全面的、可扩展的支持。
2.防止各种攻击,如会话固定攻击、点击劫持、csrf攻击等
3.支持与Servlet API、Spring MVC等Web技术集成
有关限权控制的核心主要有两点,认证和授权。认证大概意思就是,该用户是否登录,登录凭证是否过期等,认证后的用户才能进入系统。授权就是该用户有什么限权,例如是否有管理员限权。
二、使用步骤
1.引入依赖
代码如下(示例):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
在SpringBoot中父pom已经声明了Spring Security的版本,建议使用默认版本
2.让用户对象实现UserDetails接口,实现以下方法
1.boolean isAccountNonExpired();// true: 账号未过期
2.boolean isAccountNonLocked();// true: 账号未锁定
3.boolean isCredentialsNonExpired();// true: 凭证未过期
4.boolean isEnabled();// true: 账号可用
5.Collection<? extends GrantedAuthority> getAuthorities();// 权限设置
代码如下:
public class User implements UserDetails {
private int id;
private String username;
private String password;
private String salt;
private String email;
private int type;
private int status;
private String activationCode;
private String headerUrl;
private Date createTime;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", salt='" + salt + '\'' +
", email='" + email + '\'' +
", type=" + type +
", status=" + status +
", activationCode='" + activationCode + '\'' +
", headerUrl='" + headerUrl + '\'' +
", createTime=" + createTime +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return 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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getActivationCode() {
return activationCode;
}
public void setActivationCode(String activationCode) {
this.activationCode = activationCode;
}
public String getHeaderUrl() {
return headerUrl;
}
public void setHeaderUrl(String headerUrl) {
this.headerUrl = headerUrl;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public void setUsername(String username) {
this.username = username;
}
// true: 账号未过期
@Override
public boolean isAccountNonExpired() {
return false;
}
// true: 账号未锁定
@Override
public boolean isAccountNonLocked() {
return true;
}
// true: 凭证未过期
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// true: 账号可用
@Override
public boolean isEnabled() {
return true;
}
// 权限设置,限权根据自己表中定义的字段灵活修改,下面代码表示,在用户表中,type字段,1代表管理员,其他字段代表普通用户,根据对应的数字返回对应限权的字符串。
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> list = new ArrayList<>();
list.add(new GrantedAuthority() {
@Override
public String getAuthority() {
switch (type){
case 1:
return "ADMIN";
default:
return "USER";
}
}
});
return list;
}
}
3.让提供用户登录服务的UserService,实现UserDetailsService接口
该接口中主要实现loadUserByUsername(String s)方法,该方法会更据用户输入的用户名搜索得到用户对象。
代码如下:
public class UserService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
public User findUserByName(String username){
return userMapper.selectByName(username );
}
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return this.findUserByName(s);
}
}
4.对Spring Security配置类进行配置,实现灵活的限权控制
代码如下:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Override
public void configure(WebSecurity web) throws Exception {
// 忽略静态资源的访问
web.ignoring().antMatchers("/resources/**");
}
// AuthenticationManager: 认证的核心接口
// AuthenticationManagerBuilder: 用于构建AuthenticationManager的核心工具
// providerManager: AuthenticationManager默认实现类
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 内置的认证规则
//auth.userDetailsService(userService).passwordEncoder(new Pbkdf2PasswordEncoder("12345"));
// 自定义认证规则
// AuthenticationProvider: providerManager持有一组AuthenticationProvider,每一个AuthenticationProvider负责一种认证.
// 委托模式: providerManager将认委托给AuthenticationProvider.
auth.authenticationProvider(new AuthenticationProvider() {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// authentication持有请求用户输入的账号密码
String username = authentication.getName();
String password = (String)authentication.getCredentials();
// 调用service方法,对用户输入进行判断
User user = userService.findUserByName(username);
if (user == null) {
throw new UsernameNotFoundException("账号不存在!");
}
password = CommunityUtil.md5(password + user.getSalt());
if (!user.getPassword().equals(password)) {
throw new BadCredentialsException("密码不正确");
}
// 通过验证,返回对象
// principal: 主要信息; credenLials: 证书; Authorities: 限权;
return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
}
// 当前的AuthenticationProvider支持哪种类型的认证
@Override
public boolean supports(Class<?> aClass) {
// UsernamePasswordAuthenticationToken: Authentication的常用的实现类
return UsernamePasswordAuthenticationToken.class.equals(aClass);
}
});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 登录相关配置(哪个页面是登录页面?处理登陆处理的路径是哪个?成功以后怎么处理?成功时怎么处理?)
http.formLogin()
.loginPage("loginpage")
.loginProcessingUrl("lofin")
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect(request.getContextPath() + "index");
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
request.setAttribute("error", e.getMessage());
request.getRequestDispatcher("/loginpage").forward(request, response);
}
});
// 退出相关配置(退出路径?退出成功怎么办?退出失败怎么办?)
http.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect(request.getContextPath() + "index");
}
});
// 授权配置(什么限权能访问什么页面?没有限权访问失败了怎么办?)
http.authorizeRequests()
.antMatchers("/letter").hasAnyAuthority("USER", "ADMIN")
.antMatchers("admin").hasAnyAuthority("ADMIN")
.and().exceptionHandling().accessDeniedPage("/denied");
// 增加Filter,处理验证码
http.addFilterBefore(new Filter() {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (request.getServletPath().equals("/login")) {
String verifyCode = request.getParameter("verifyCode");
if (verifyCode == null || verifyCode.equalsIgnoreCase("1234")) {
request.setAttribute("error", "验证码错误!");
request.getRequestDispatcher("/loginpage").forward(request, response);
}
}
}
}, UsernamePasswordAuthenticationFilter.class);
// 记住我
http.rememberMe()
.tokenRepository(new InMemoryTokenRepositoryImpl())
.tokenValiditySeconds(3600 * 24)
.userDetailsService(userService);
}
}
总结
本文仅仅简单介绍了Spring Security的使用,Spring Security的底层是由16个过滤器组成,理解该过滤器极有利于我们对Java应用的理解。标签:return,String,void,request,无标题,Override,public 来源: https://blog.csdn.net/bythy/article/details/123307188