赞
踩
认证+授权
主要有两个主要功能:“认证”,是建立一个他声明的主体的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统),通俗点说就是系统认为用户是否能登录。一般在拦截器中进行拦截用户信息进行认证。 “授权"指确定一个主体是否允许在你的应用程序执行一个动作的过程,一般是在Security中进行接口权限配置,查看用户是否具有对应接口权限。通俗点讲就是系统判断用户是否有权限去做某些事情。
相应语法:
.successForwardUrl()登录成功后跳转地址
.loginPage()登录页面
.loginProcessingurl登录页面表单提交地址,此地址可以不真实存在。
antMatchers():匹配内容permitAll():允许
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
SpringSecurty提供了多种验证方法,本次采用用户名/密码的方式进行验证。所以需要实现UserDetailsService接口中的loadUserByUserName方法,从数据库中查找对应的数据然后与用户输入数据进行对比,所以需要返回一个UserDetails对象。
本项目中使用student作为用户表,同时使用type作为权限标识
- import com.baomidou.mybatisplus.annotation.IdType;
- import com.baomidou.mybatisplus.annotation.TableId;
- import lombok.Data;
- import lombok.EqualsAndHashCode;
- import lombok.experimental.Accessors;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.userdetails.UserDetails;
-
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Date;
- import java.util.List;
-
- @Data
- @EqualsAndHashCode(callSuper = false)
- @Accessors(chain = true)
- public class Student implements UserDetails {
-
- @TableId(value = "id", type = IdType.AUTO)
- private Integer id;
-
- private String studentName;
-
- private String studentSex;
-
- private String studentSubject;
-
- private String username;
-
- private String password;
-
- private String salt;
-
- private String email;
-
- private Integer type;
-
- private Integer status;
-
- private String activationCode;
-
- private String headerUrl;
-
- private Date createTime;
-
- private String studentPhone;
- // true: 账号未过期.
- @Override
- public boolean isAccountNonExpired() {
- return true;
- }
-
- // true: 账号未锁定.
- @Override
- public boolean isAccountNonLocked() {
- return true;
- }
-
- // true: 凭证未过期.
- @Override
- public boolean isCredentialsNonExpired() {
- return true;
- }
-
- // true: 账号可用.
- @Override
- public boolean isEnabled() {
- return true;
- }
-
- @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;
- }
-
- }

创建getAuthorities方法 获取用户权限,同时Type的字段值代表了用户的权限
自定义实现验证权限类型
- public interface StudentService extends IService<Student>, UserDetailsService {
-
-
-
- Collection<? extends GrantedAuthority> getAuthorities(Integer id);
- }
- @Service
- public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
- @Override
- public Collection<? extends GrantedAuthority> getAuthorities(Integer id) {
- Student student = this.findStudentById(id);
-
- List<GrantedAuthority> list = new ArrayList<>();
- list.add(new GrantedAuthority() {
- @Override
- public String getAuthority() {
- switch (student.getType()) {
- case 1:
- return AUTHORITY_ADMIN;
- case 2:
- return AUTHORITY_MODERATOR;
- default:
- return AUTHORITY_USER;
- }
- }
- });
- return list;
- }
- }

可以自定义也可以不使用这一步
-
- public interface CommunityConstant {
-
- /**
- 权限:普通用户ID
- **/
- String AUTHORITY_USER="user";
-
- /**
- 权限:管理员ID
- **/
- String AUTHORITY_ADMIN="admin";
-
- /**
- 权限:管理员ID
- **/
- String AUTHORITY_MODERATOR="moderator";
-
- }

将student中的用户信息导入到Security中,使得安全配置生效
//构建用户认证结果,并存入SecurityContext,以便于Security进行授权
Authentication authentication=new UsernamePasswordAuthenticationToken(
student,student.getPassword(),studentService.getAuthorities(student.getId()));SecurityContextHolder.setContext(new SecurityContextImpl(authentication));
本次采用拦截器的形式来进行构建用户认证结果,并存入SecurityContext,以便于Security进行授权,如果loadUserByName验证通过,则此处没有问题,即可验证通过。
- @Component
- public class LoginInterceptor implements HandlerInterceptor {
- @Autowired
- private HostHolder hostHolder;
-
- @Autowired
- private StudentService studentService;
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-
- String ticket = CookieUtil.getValue(request, "ticket"); //调用存在cookie里的数据
-
- if (ticket != null) {
- // 查询凭证
- LoginTicket loginTicket = studentService.findLoginTicket(ticket);
- // 检查凭证是否有效
- if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) {
-
- // 根据凭证查询用户
- Student student = studentService.findStudentById(loginTicket.getUserId());
- // 在本次请求中持有用户
- hostHolder.setStudent(student);
-
- //构建用户认证结果,并存入SecurityContext,以便于Security进行授权
- Authentication authentication=new UsernamePasswordAuthenticationToken(
- student,student.getPassword(),studentService.getAuthorities(student.getId()));
-
- SecurityContextHolder.setContext(new SecurityContextImpl(authentication));
- return true;
- }else{
- response.sendRedirect(request.getContextPath()+"/login"); //转发请求 到request.getContextPath() + "/login";
- }
- }else {
- response.sendRedirect(request.getContextPath()+"/login"); //request.getContextPath()为请求目录 localhost:8080/sushe/
- }
- return false;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- Student student = hostHolder.getStudent();
- if (student != null && modelAndView != null) {
- modelAndView.addObject("loginStudent", student);
- }
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- hostHolder.clear();
- }
- }

在认证通过之后我们可以在security配置中进行用户,管理员等不同角色对接口的访问限制。
.antMatcher{} 对应相关接口
.hasAnyAuthority{} 对应相关用户
- package com.example.sushe.config;
-
-
- import com.example.sushe.util.CommunityConstant;
- import com.example.sushe.util.CommunityUtil;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.security.access.AccessDeniedException;
- import org.springframework.security.config.annotation.web.builders.HttpSecurity;
- import org.springframework.security.config.annotation.web.builders.WebSecurity;
- import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
- import org.springframework.security.core.AuthenticationException;
- import org.springframework.security.web.AuthenticationEntryPoint;
- import org.springframework.security.web.access.AccessDeniedHandler;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.io.PrintWriter;
-
-
- @Configuration
- public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant {
-
- @Override
- public void configure(WebSecurity web) throws Exception {
- web.ignoring().antMatchers("/resources/**");
- }
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- //授权
- http.authorizeRequests()
- .antMatchers(
- "/person/findAll"
- )
- .hasAnyAuthority(
- AUTHORITY_USER,
- AUTHORITY_ADMIN,
- AUTHORITY_MODERATOR
- )
- .antMatchers(
- "/person/add/*","/person/update/*","/person/updatePerson","/person/delete","/subject/*"
- )
- .hasAnyAuthority(
- AUTHORITY_ADMIN
- )
- .anyRequest().permitAll()
- .and().csrf().disable();
-
-
- //权限不够时的出理
- http.exceptionHandling()
- .authenticationEntryPoint(new AuthenticationEntryPoint() {
- //没有登陆
- @Override
- public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
- String xRequestedWith = request.getHeader("x-requested-with");
- if("XMLHttpRequest".equals(xRequestedWith)){
- response.setContentType("application/plain/character=utf-8");
- PrintWriter writer=response.getWriter();
- writer.write((CommunityUtil.getJSONString(403,"你还没有登录呕")));
- }else{
- response.sendRedirect(request.getContextPath()+"/login");
- }
- }
- })
- .accessDeniedHandler(new AccessDeniedHandler() {
- //权限不足
- @Override
- public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
- String xRequestedWith = request.getHeader("x-requested-with");
- if("XMLHttpRequest".equals(xRequestedWith)){
- response.setContentType("application/plain/character=utf-8");
- PrintWriter writer=response.getWriter();
- writer.write((CommunityUtil.getJSONString(403,"没有访问此页面的权限")));
- }else{
- response.sendRedirect(request.getContextPath()+"/error");
- }
- }
- });
-
- //Security底层会默认拦截/logout请求,进行退出处理
- //覆盖它原来的逻辑
- http.logout().logoutUrl("/Securitylogout");
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。