@CurrentUser获取当前登录用户信息

首先创建一个项目,项目需要有登录的功能。

1、首先需要用到token,在用户表中存放一个token,每当用户登录的时候就用UUID生成一个token替换之前的token,并保存(修改)到缓存中。

2、创建@CurrentUser注解。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)          // 可用在方法的参数上
@Retention(RetentionPolicy.RUNTIME)     // 运行时有效
public @interface CurrentUser {
    
    
}

3、写一个组件,用来存放和取出token

@Component
public class UserCache {
    
    

    private static final String HELPER_KEY="user:temp:";

    private static UserCache userCache;
    @Resource
    private TestUserService testUserService;
    @Resource
    private RedisTemplate<String, TestUser> redisTemplate;

    @PostConstruct
    public void init() {
    
    
        userCache = this;
        userCache.testUserService = this.testUserService;
        userCache.redisTemplate=this.redisTemplate;
    }

    /**
     * 服务器端的本地缓存时间为24小时
     */
    private static final long EXPIRE_TIME = 24L;
    /**
     * 根据token获取Pregnant对象
     *
     * @param token
     * @return
     */
    public static TestUser getUserByToken(String token) {
    
    
        TestUser testUser = userCache.redisTemplate.boundValueOps(HELPER_KEY + token).get();
        if (testUser == null){
    
    
            TestUser helper = userCache.testUserService.
                    findByToken(token);
            if (helper == null){
    
    
                throw new UnauthorizedException(ErrorCode.Unauthorized);
            }
            userCache.redisTemplate.boundValueOps(HELPER_KEY+token).set(testUser,EXPIRE_TIME, TimeUnit.HOURS);
        }
        return testUser;
    }

    /**
     * 主动放入缓存
     *
     * @param token
     * @param dto
     */
    public static void put(String token, TestUser dto) {
    
    
        userCache.redisTemplate.boundValueOps(HELPER_KEY+token).set(dto,EXPIRE_TIME,TimeUnit.HOURS);
    }

4、配置PublicInterface(用来标注可以不使用token)

@Target(ElementType.METHOD)          // 可用在方法的参数上
@Retention(RetentionPolicy.RUNTIME)     // 运行时有效
public @interface PublicInterface {
    
    
}

5、配置一个拦截器,判断是否存在token和token是否有效

public class AuthenticationInterceptor implements HandlerInterceptor {
    
    

    /**
     * 存储URL
     */
    protected final static Set<String> ignoreUrls = ConcurrentHashMap.newKeySet();

    private Logger logger = LoggerFactory.getLogger(AuthenticationInterceptor.class);
    //不拦截哪些请求
    static {
    
    
        ignoreUrls.add("/error");
        ignoreUrls.add("/images");
        ignoreUrls.add("/static");
        ignoreUrls.add("/webjars");
        ignoreUrls.add("/Users/login");
    }


    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
    
    

        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
    
    
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        // 判断接口是否需要登录
        PublicInterface methodAnnotation = method.getAnnotation(PublicInterface.class);
        if (methodAnnotation != null) {
    
    
            return true;
        }
        if (isIntercept(request.getServletPath())) {
    
    
            // 从http请求头中取出token
            String token = request.getHeader("token");
            if (token == null) {
    
    
                throw new UnauthorizedException(ErrorCode.TokenNotExist);
            }

            //判断token时候合法
            TestUser testUser = UserCache.getUserByToken(token);
            if (testUser == null) {
    
    
                throw new UnauthorizedException(ErrorCode.TokenInvalid);
            }

            // 将当前用户放入request以备@CurrentUser注解使用
            request.setAttribute("currentUser", testUser);
            return true;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    
    
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    
    
    }

    /**
     * 判断是否需要拦截
     *
     * @param servletPath
     * @return
     */
    private boolean isIntercept(String servletPath) {
    
    
        for (String url : ignoreUrls) {
    
    
            if (servletPath.startsWith(url)) {
    
    
                return false;
            }
        }
        return true;
    }

6、配置解析器,用来获取当前登录用户的信息

public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver {
    
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
    
    
        return parameter.getParameterType().isAssignableFrom(TestUser.class)
                && parameter.hasParameterAnnotation(CurrentUser.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
    
    
        TestUser dto = (TestUser) webRequest.getAttribute("currentUser", RequestAttributes.SCOPE_REQUEST);
        if (dto != null) {
    
    
            return dto;
        }
        throw new MissingServletRequestPartException("currentUser");
    }
}

7、注入进程序

@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    
    

    //配置视图组件
    @Bean
    public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
    
    
        WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
    
    
            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
    
    
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/login.html").setViewName("login");
                registry.addViewController("/home.html").setViewName("home");
                registry.addViewController("/employee.html").setViewName("employee");
                registry.addViewController("/addEmployee.html").setViewName("addEmployee");
                registry.addViewController("/updateEmployee.html").setViewName("updateEmployee");
            }
        };
        return adapter;
    }

    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    
    
        argumentResolvers.add(currentUserMethodArgumentResolver());
        super.addArgumentResolvers(argumentResolvers);
    }

    public void addInterceptors(InterceptorRegistry registry) {
    
    
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");
        super.addInterceptors(registry);
    }
    @Bean
    public UserMethodArgumentResolver currentUserMethodArgumentResolver() {
    
    
        return new UserMethodArgumentResolver();
    }

    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
    
    
        return new AuthenticationInterceptor();
    }

8、登录的controller

@Controller
public class LoginController {
    
    

    @Resource
    TestUserService testUserService;

    @PostMapping ("/Users/login")
    @ResponseBody
    public Map<String,String> userLogin(@RequestParam("userName") String userName,
                            @RequestParam("userPass") String userPass, HttpSession session){
    
    
        Map<String,String> map = new HashMap<>();
        TestUser user = testUserService.findUserLogin(userName, userPass);
        if (user != null){
    
    
            String token = UUID.randomUUID().toString().replaceAll("-", "");
            //保存token到redis并更新数据库
            user.setToken(token);
            TestUser testUser = testUserService.updateTestUser(user);
            session.setAttribute("token",token);
            UserCache.put(token, testUser);
            map.put("result","登录成功");
        }else {
    
    
            map.put("result","用户名或密码错误");
        }
        return map;
    }
}

9、登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <script src="/js/jquery-2.1.3.min.js"></script>
</head>
<body>
    <div>
        账户:<input type="text" id="userName"/>
        <br/>
        密码:<input type="text" id="userPass"/>
        <br/>
        <input type="button" id="login" value="登录"/>
    </div>
</body>
<script>
    $("#login").click(function (){
     
     
        let userName = $("#userName").val();
        let userPass = $("#userPass").val();
        $.ajax({
     
     
            type:"POST",
            url:"/Users/login",
            data:{
     
     
                userName:userName,
                userPass:userPass
            },
            success:function (data){
     
     
                if(data.result == "登录成功"){
     
     
                    alert("登录成功");
                    window.location.href = 'http://localhost:8080/home.html';
                }else{
     
     
                    alert(data.result);
                }
            }
        })
    })
</script>
</html>

10、登录之后跳转页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <script src="/js/jquery-2.1.3.min.js"></script>
</head>
<body>
<input type="hidden" id="token" th:value="${session.token}"/>
<div>
    <div>运营页面</div>
    <div id="employee">员工管理</div>
    <div>用户管理</div>
    <div id="findEmployee">财务统计</div>
</div>
</body>
<script>
    $("#employee").click(function (){
     
     
        let token = $("#token").val();
        $.ajax({
     
     
            headers:{
     
     
                token:token
            },
            type:"Get",
            url:"/Users/findEmployeeAll",
            date:{
     
     },
            success:function (data){
     
     
                alert(data)
            }
        })
    })
    $("#findEmployee").click(function (){
     
     
        let token = $("#token").val();
        $.ajax({
     
     
            type:"Get",
            url:"/Users/findEmployee",
            date:{
     
     },
            success:function (data){
     
     
                alert(data)
            }
        })
    })
</script>
</html>

11、验证

    /**
     * 需要携带token的接口
     * @return
     */
    @GetMapping("/Users/findEmployeeAll")
    @ResponseBody
    public String findEmployeeAll(@CurrentUser TestUser user){
    
    
        return "这是验证token的接口"+user.getToken();
    }

    /**
     * 使用@PublicInterface,不需要携带token
     * @param user
     * @return
     */
    @GetMapping("/Users/findEmployee")
    @ResponseBody
    @PublicInterface
    public String findEmployee(TestUser user){
    
    
        return "这是验证token的接口";
    }

猜你喜欢

转载自blog.csdn.net/javaasd/article/details/114892265